diff --git a/0142-pull-failure-shows-error-reason.patch b/0142-pull-failure-shows-error-reason.patch new file mode 100644 index 0000000000000000000000000000000000000000..c156d614ad4cd93efe651122ac4f1134599bb9ad --- /dev/null +++ b/0142-pull-failure-shows-error-reason.patch @@ -0,0 +1,27 @@ +From dd3f733949a0c6c9256a63b54079e9a7b8aa7fe6 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Fri, 25 Oct 2024 02:50:01 +1400 +Subject: [PATCH 142/156] pull failure shows error reason + +Signed-off-by: zhongtao +--- + src/daemon/entry/connect/grpc/grpc_images_service.cc | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/daemon/entry/connect/grpc/grpc_images_service.cc b/src/daemon/entry/connect/grpc/grpc_images_service.cc +index 32f0446e..6135945a 100644 +--- a/src/daemon/entry/connect/grpc/grpc_images_service.cc ++++ b/src/daemon/entry/connect/grpc/grpc_images_service.cc +@@ -691,6 +691,9 @@ Status ImagesServiceImpl::PullImage(ServerContext *context, const PullImageReque + stream.writer = (void *)writer; + + ret = cb->image.pull(image_req, &stream, &image_res); ++ if (image_res->errmsg != NULL) { ++ errmsg = image_res->errmsg; ++ } + free_image_pull_image_request(image_req); + free_image_pull_image_response(image_res); + if (ret == 0) { +-- +2.34.1 + diff --git a/0143-move-CGROUP2_SUPER_MAGIC-define-to-cgroup.c.patch b/0143-move-CGROUP2_SUPER_MAGIC-define-to-cgroup.c.patch new file mode 100644 index 0000000000000000000000000000000000000000..01f25aee7a54cae87c8d8460402c7d4310c95a17 --- /dev/null +++ b/0143-move-CGROUP2_SUPER_MAGIC-define-to-cgroup.c.patch @@ -0,0 +1,44 @@ +From d0bb2c00769ab41ada532a04338b91032d7ada2e Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Sat, 26 Oct 2024 16:59:09 +1400 +Subject: [PATCH 143/156] move CGROUP2_SUPER_MAGIC define to cgroup.c + +Signed-off-by: zhongtao +--- + src/daemon/common/cgroup/cgroup.c | 4 ++++ + src/daemon/common/cgroup/cgroup_v2.c | 4 ---- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/daemon/common/cgroup/cgroup.c b/src/daemon/common/cgroup/cgroup.c +index 77fafdae..a6846c03 100644 +--- a/src/daemon/common/cgroup/cgroup.c ++++ b/src/daemon/common/cgroup/cgroup.c +@@ -36,6 +36,10 @@ + #define CGROUP_SUPER_MAGIC 0x27e0eb + #endif + ++#ifndef CGROUP2_SUPER_MAGIC ++#define CGROUP2_SUPER_MAGIC 0x63677270 ++#endif ++ + static cgroup_ops g_cgroup_ops; + + static int get_cgroup_version_for_init(void) +diff --git a/src/daemon/common/cgroup/cgroup_v2.c b/src/daemon/common/cgroup/cgroup_v2.c +index ce72e6c4..078425d2 100644 +--- a/src/daemon/common/cgroup/cgroup_v2.c ++++ b/src/daemon/common/cgroup/cgroup_v2.c +@@ -52,10 +52,6 @@ + #define CGROUP2_CPUSET_CPUS_EFFECTIVE_PATH CGROUP_MOUNTPOINT"/cpuset.cpus.effective" + #define CGROUP2_CPUSET_MEMS_EFFECTIVE_PATH CGROUP_MOUNTPOINT"/cpuset.mems.effective" + +-#ifndef CGROUP2_SUPER_MAGIC +-#define CGROUP2_SUPER_MAGIC 0x63677270 +-#endif +- + static int get_value_ull_v2(const char *content, const char *match, void *result) + { + uint64_t ull_result = 0; +-- +2.34.1 + diff --git a/0144-update-centos-build-script.patch b/0144-update-centos-build-script.patch new file mode 100644 index 0000000000000000000000000000000000000000..4400afe821aab275bb17f09af423df0ec416a227 --- /dev/null +++ b/0144-update-centos-build-script.patch @@ -0,0 +1,189 @@ +From 10aa1ba26eecdf044c1a97e05db53d286e19a3af Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Sat, 26 Oct 2024 18:24:21 +1400 +Subject: [PATCH 144/156] update centos build script + +Signed-off-by: zhongtao +--- + CI/dockerfiles/Dockerfile-centos | 10 ++- + docs/build_docs/README_zh.md | 4 + + .../script/install_iSulad_on_Centos_7.sh | 83 +++---------------- + 3 files changed, 23 insertions(+), 74 deletions(-) + +diff --git a/CI/dockerfiles/Dockerfile-centos b/CI/dockerfiles/Dockerfile-centos +index af3ce035..0b11014b 100644 +--- a/CI/dockerfiles/Dockerfile-centos ++++ b/CI/dockerfiles/Dockerfile-centos +@@ -24,6 +24,11 @@ + FROM centos:7.6.1810 + MAINTAINER LiFeng + ++RUN sed -i 's/mirror.centos.org/archive.kernel.org\/centos-vault/g' /etc/yum.repos.d/*.repo ++RUN sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/*.repo ++RUN sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/*.repo ++RUN echo "sslverify=false" | tee -a /etc/yum.conf ++ + # Install dependency package + RUN yum clean all && yum makecache && yum install -y epel-release && yum swap -y fakesystemd systemd && \ + yum update -y && \ +@@ -113,6 +118,9 @@ RUN git config --global http.sslverify false + # install rust + RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + ++RUN mkdir -p /root/.cargo/ ++RUN touch ${HOME}/.cargo/config ++ + # configure rust + RUN echo "[source.crates-io]" >> ${HOME}/.cargo/config && \ + echo "[source.local-registry]" >> ${HOME}/.cargo/config && \ +@@ -286,7 +294,7 @@ RUN export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH && \ + make install && \ + ldconfig + +-RUN dnf install -y ncurses-devel && dnf clean all ++RUN yum install -y ncurses-devel && yum clean all + + VOLUME [ "/sys/fs/cgroup" ] + CMD ["/usr/sbin/init"] +diff --git a/docs/build_docs/README_zh.md b/docs/build_docs/README_zh.md +index f27fbc4f..6450bf7e 100644 +--- a/docs/build_docs/README_zh.md ++++ b/docs/build_docs/README_zh.md +@@ -40,6 +40,8 @@ $ cd iSulad/docs/build_docs/guide/script + $ sudo ./install_iSulad_on_Centos_7.sh + ``` + ++若需要在centos容器中编译iSulad,可参照iSulad编译可使用的镜像dockerfile[Dockerfile-ubuntu](../../CI/dockerfiles/Dockerfile-ubuntu)。 ++ + ### Ubuntu + + 我们同样在代码仓中提供了在Ubuntu上自动化安装的脚本: [install_iSulad_on_Ubuntu_20_04_LTS](./guide/script/install_iSulad_on_Ubuntu_20_04_LTS.sh),您只需要执行这个脚本就可以自动编译安装iSulad以及其依赖的组件。 +@@ -51,6 +53,8 @@ $ sudo chmod +x ./install_iSulad_on_Ubuntu_20_04_LTS.sh + $ sudo ./install_iSulad_on_Ubuntu_20_04_LTS.sh + ``` + ++若需要在ubuntu容器中编译iSulad,可参照iSulad编译可使用的镜像dockerfile[Dockerfile-centos](../../CI/dockerfiles/)。 ++ + ## 构建指南 + + 我们提供了多种构建iSulad的方式: +diff --git a/docs/build_docs/guide/script/install_iSulad_on_Centos_7.sh b/docs/build_docs/guide/script/install_iSulad_on_Centos_7.sh +index b268d777..d83520e1 100755 +--- a/docs/build_docs/guide/script/install_iSulad_on_Centos_7.sh ++++ b/docs/build_docs/guide/script/install_iSulad_on_Centos_7.sh +@@ -5,93 +5,29 @@ set -x + set -e + + # install neccessary packages +-yum install -y patch automake autoconf libtool cmake make libcap libcap-devel libselinux libselinux-devel libseccomp libseccomp-devel yajl-devel git libcgroup tar python3 python3-pip device-mapper-devel libcurl-devel zlib-devel glibc-headers openssl-devel gcc gcc-c++ systemd-devel systemd-libs golang libtar libtar-devel which ++# yum install -y patch automake autoconf libtool cmake make libcap libcap-devel libselinux libselinux-devel libseccomp libseccomp-devel yajl-devel git libcgroup tar python3 python3-pip device-mapper-devel libcurl-devel zlib-devel glibc-headers openssl-devel gcc gcc-c++ systemd-devel systemd-libs golang libtar libtar-devel which + + # export LDFLAGS + export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH + export LD_LIBRARY_PATH=/usr/local/lib:/usr/lib:$LD_LIBRARY_PATH +- echo "/usr/local/lib" >> /etc/ld.so.conf ++echo "/usr/local/lib" >> /etc/ld.so.conf + + BUILD_DIR=/tmp/build_isulad + + rm -rf $BUILD_DIR + mkdir -p $BUILD_DIR + +-# build libarchive +-cd $BUILD_DIR +-git clone https://gitee.com/src-openeuler/libarchive.git +-cd libarchive +-git checkout -b openEuler-20.03-LTS-tag openEuler-20.03-LTS-tag +-tar -zxvf libarchive-3.4.1.tar.gz +-cd libarchive-3.4.1 +-patch -p1 -F1 -s < ../libarchive-uninitialized-value.patch +-cd build +-cmake -DCMAKE_USE_SYSTEM_LIBRARIES=ON ../ +-make -j $(nproc) +-make install +-ldconfig +- +-# build protobuf +-cd $BUILD_DIR +-git clone https://gitee.com/src-openeuler/protobuf.git +-cd protobuf +-git checkout openEuler-20.03-LTS-tag +-tar -xzvf protobuf-all-3.9.0.tar.gz +-cd protobuf-3.9.0 +-./autogen.sh +-./configure +-make -j $(nproc) +-make install +-ldconfig +- +-# build c-ares +-cd $BUILD_DIR +-git clone https://gitee.com/src-openeuler/c-ares.git +-cd c-ares +-git checkout openEuler-20.03-LTS-tag +-tar -xzvf c-ares-1.15.0.tar.gz +-cd c-ares-1.15.0 +-autoreconf -if +-./configure --enable-shared --disable-dependency-tracking +-make -j $(nproc) +-make install +-ldconfig +- +-# build grpc +-cd $BUILD_DIR +-git clone https://gitee.com/src-openeuler/grpc.git +-cd grpc +-git checkout openEuler-20.03-LTS-tag +-tar -xzvf grpc-1.22.0.tar.gz +-cd grpc-1.22.0 +-make -j $(nproc) +-make install +-ldconfig +- +-# build libwebsockets +-cd $BUILD_DIR +-git clone https://gitee.com/src-openeuler/libwebsockets.git +-cd libwebsockets +-git checkout openEuler-20.03-LTS-tag +-tar -xzvf libwebsockets-2.4.2.tar.gz +-cd libwebsockets-2.4.2 +-patch -p1 -F1 -s < ../libwebsockets-fix-coredump.patch +-mkdir build +-cd build +-cmake -DLWS_WITH_SSL=0 -DLWS_MAX_SMP=32 -DCMAKE_BUILD_TYPE=Debug ../ +-make -j $(nproc) +-make install +-ldconfig +- + # build lxc + cd $BUILD_DIR + git clone https://gitee.com/src-openeuler/lxc.git + cd lxc ++git config --global --add safe.directory $BUILD_DIR/lxc/lxc-5.0.2 + ./apply-patches +-cd lxc-4.0.3 +-./autogen.sh +-./configure +-make -j ++cd lxc-5.0.2 ++sed -i 's/return open(rpath, (int)((unsigned int)flags | O_CLOEXEC));/return open(rpath, (int)((unsigned int)flags | O_CLOEXEC), 0);/g' src/lxc/isulad_utils.c ++meson setup -Disulad=true \ ++ -Dprefix=/usr build ++meson compile -C build + make install + + # build lcr +@@ -118,8 +54,9 @@ make install + cd $BUILD_DIR + git clone https://gitee.com/openeuler/iSulad.git + cd iSulad ++sed -i 's/-O2 -Wall -fPIE/-O2 -Wall -fPIE -std=gnu99/g' cmake/set_build_flags.cmake + mkdir build + cd build +-cmake .. ++cmake -DDISABLE_WERROR=on ../ + make + make install +-- +2.34.1 + diff --git a/0145-cni-change-error-info.patch b/0145-cni-change-error-info.patch new file mode 100644 index 0000000000000000000000000000000000000000..7f4e256b2e8e6b932f646cef146834be6de01b95 --- /dev/null +++ b/0145-cni-change-error-info.patch @@ -0,0 +1,97 @@ +From 445642718fd3dd7867aad9fc8e6eb5b7dafadcb6 Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Fri, 1 Nov 2024 12:56:38 +0800 +Subject: [PATCH 145/156] cni:change error info + +Signed-off-by: liuxu +--- + .../modules/network/cni_operator/cni_operate.c | 8 ++++---- + .../network/cni_operator/libcni/libcni_api.c | 14 +++++++++++++- + .../network/cni_operator/libcni/libcni_api.h | 2 +- + 3 files changed, 18 insertions(+), 6 deletions(-) + +diff --git a/src/daemon/modules/network/cni_operator/cni_operate.c b/src/daemon/modules/network/cni_operator/cni_operate.c +index 6db6db51..80a2642d 100644 +--- a/src/daemon/modules/network/cni_operator/cni_operate.c ++++ b/src/daemon/modules/network/cni_operator/cni_operate.c +@@ -731,13 +731,13 @@ static int update_runtime_conf_cni_args_by_cached(cni_cached_info *info, struct + return 0; + } + +-static int get_configs_from_cached(const char *network, struct runtime_conf *rc, char **conf_list) ++static int get_configs_from_cached(const char *network, const char *cni_version, struct runtime_conf *rc, char **conf_list) + { + int ret = 0; + size_t i; + cni_cached_info *info = NULL; + +- info = cni_get_network_list_cached_info(network, rc); ++ info = cni_get_network_list_cached_info(network, cni_version, rc); + if (info == NULL) { + return 0; + } +@@ -857,7 +857,7 @@ int check_network_plane(const struct cni_manager *manager, const struct cni_netw + goto out; + } + +- ret = get_configs_from_cached(list->list->name, rc, NULL); ++ ret = get_configs_from_cached(list->list->name, list->list->cni_version, rc, NULL); + if (ret != 0) { + ERROR("Get cached info failed"); + ret = -1; +@@ -901,7 +901,7 @@ int detach_network_plane(const struct cni_manager *manager, const struct cni_net + goto out; + } + +- ret = get_configs_from_cached(list->list->name, rc, NULL); ++ ret = get_configs_from_cached(list->list->name, list->list->cni_version, rc, NULL); + if (ret != 0) { + ERROR("Get cached info failed"); + ret = -1; +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 7ba983af..c55c8e9d 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/libcni_api.c ++++ b/src/daemon/modules/network/cni_operator/libcni/libcni_api.c +@@ -81,13 +81,25 @@ struct cni_opt_result *cni_get_network_list_cached_result(const struct cni_netwo + return result; + } + +-cni_cached_info *cni_get_network_list_cached_info(const char *network, const struct runtime_conf *rc) ++cni_cached_info *cni_get_network_list_cached_info(const char *network, const char *cni_version, const struct runtime_conf *rc) + { ++ bool greater = false; + if (network == NULL) { + ERROR("Empty network"); + return NULL; + } + ++ if (util_version_greater_than_or_equal_to(cni_version, SUPPORT_CACHE_AND_CHECK_VERSION, &greater) != 0) { ++ ERROR("Invalid cni version %s", cni_version); ++ return NULL; ++ } ++ ++ // CACHE was added in CNI spec version 0.4.0 and higher ++ if (!greater) { ++ WARN("result version: %s is too old, do not save this cache", cni_version); ++ return NULL; ++ } ++ + return cni_cache_read(g_module_conf.cache_dir, network, rc); + } + +diff --git a/src/daemon/modules/network/cni_operator/libcni/libcni_api.h b/src/daemon/modules/network/cni_operator/libcni/libcni_api.h +index 2f10d6e9..bf16f168 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/libcni_api.h ++++ b/src/daemon/modules/network/cni_operator/libcni/libcni_api.h +@@ -75,7 +75,7 @@ bool cni_module_init(const char *cache_dir, const char * const *paths, size_t pa + struct cni_opt_result *cni_get_network_list_cached_result(const struct cni_network_list_conf *list, + const struct runtime_conf *rc); + +-cni_cached_info *cni_get_network_list_cached_info(const char *network, const struct runtime_conf *rc); ++cni_cached_info *cni_get_network_list_cached_info(const char *network, const char *cni_version, const struct runtime_conf *rc); + + int cni_add_network_list(const struct cni_network_list_conf *list, const struct runtime_conf *rc, + struct cni_opt_result **pret); +-- +2.34.1 + diff --git a/0146-bugfix-for-sem_wait-call-when-errno-is-EINTR.patch b/0146-bugfix-for-sem_wait-call-when-errno-is-EINTR.patch new file mode 100644 index 0000000000000000000000000000000000000000..38992e34255e5fa6027467931017e8f5c099a9d7 --- /dev/null +++ b/0146-bugfix-for-sem_wait-call-when-errno-is-EINTR.patch @@ -0,0 +1,233 @@ +From 70f5e98110b2c63755f283712eebbd075787081b Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Tue, 5 Nov 2024 03:15:04 +1400 +Subject: [PATCH 146/156] bugfix for sem_wait call when errno is EINTR + +Signed-off-by: zhongtao +--- + src/cmd/isula/base/start.c | 4 +++- + src/cmd/isula/client_console.c | 4 +++- + src/cmd/isula/stream/attach.c | 8 ++++++-- + src/cmd/isula/stream/exec.c | 4 +++- + src/cmd/isulad-shim/process.c | 4 +++- + src/cmd/isulad/main.c | 8 ++++++-- + src/daemon/entry/connect/grpc/grpc_containers_service.cc | 8 ++++++-- + src/daemon/entry/cri/streams/attach_serve.cc | 4 +++- + src/daemon/entry/cri/streams/websocket/ws_server.cc | 5 ++++- + src/daemon/modules/events/collector.c | 8 ++++++-- + src/daemon/modules/service/io_handler.c | 4 +++- + 11 files changed, 46 insertions(+), 15 deletions(-) + +diff --git a/src/cmd/isula/base/start.c b/src/cmd/isula/base/start.c +index 6a066638..3f8c13ee 100644 +--- a/src/cmd/isula/base/start.c ++++ b/src/cmd/isula/base/start.c +@@ -193,7 +193,9 @@ out: + void client_wait_fifo_exit(const struct client_arguments *args) + { + if (args->custom_conf.attach_stdin || args->custom_conf.attach_stdout || args->custom_conf.attach_stderr) { +- sem_wait(&g_console_waitexit_sem); ++ while(sem_wait(&g_console_waitexit_sem) == -1 && errno == EINTR) { ++ continue; ++ } + } + } + +diff --git a/src/cmd/isula/client_console.c b/src/cmd/isula/client_console.c +index 555f59b6..fb6f6c05 100644 +--- a/src/cmd/isula/client_console.c ++++ b/src/cmd/isula/client_console.c +@@ -259,7 +259,9 @@ int start_client_console_thread(struct command_fifo_config *console_fifos, bool + return -1; + } + +- sem_wait(console_fifos->wait_open); ++ while(sem_wait(console_fifos->wait_open) == -1 && errno == EINTR) { ++ continue; ++ } + + return 0; + } +diff --git a/src/cmd/isula/stream/attach.c b/src/cmd/isula/stream/attach.c +index b61c9350..bc3eb141 100644 +--- a/src/cmd/isula/stream/attach.c ++++ b/src/cmd/isula/stream/attach.c +@@ -285,7 +285,9 @@ static int container_wait_thread(struct client_arguments *args, uint32_t *exit_c + (void)sem_destroy(&sem_started); + return -1; + } +- (void)sem_wait(&sem_started); ++ while(sem_wait(&sem_started) == -1 && errno == EINTR) { ++ continue; ++ } + (void)sem_destroy(&sem_started); + return 0; + } +@@ -366,7 +368,9 @@ static int client_attach(struct client_arguments *args, uint32_t *exit_code) + } + + #ifndef GRPC_CONNECTOR +- sem_wait(&g_attach_waitexit_sem); ++ while(sem_wait(&g_attach_waitexit_sem) == -1 && errno == EINTR) { ++ continue; ++ } + #endif + + if (clock_gettime(CLOCK_REALTIME, &ts) == -1) { +diff --git a/src/cmd/isula/stream/exec.c b/src/cmd/isula/stream/exec.c +index cacb0278..6eab4d4f 100644 +--- a/src/cmd/isula/stream/exec.c ++++ b/src/cmd/isula/stream/exec.c +@@ -380,7 +380,9 @@ static int local_cmd_exec(struct client_arguments *args, uint32_t *exit_code) + ret = client_exec(args, command_fifos, exit_code); + if (ret == 0 && + (args->custom_conf.attach_stdin || args->custom_conf.attach_stdout || args->custom_conf.attach_stderr)) { +- sem_wait(&g_command_waitexit_sem); ++ while(sem_wait(&g_command_waitexit_sem) == -1 && errno == EINTR) { ++ continue; ++ } + } + out: + delete_command_fifo(command_fifos); +diff --git a/src/cmd/isulad-shim/process.c b/src/cmd/isulad-shim/process.c +index 18fae03f..11903a5c 100644 +--- a/src/cmd/isulad-shim/process.c ++++ b/src/cmd/isulad-shim/process.c +@@ -1237,7 +1237,9 @@ int process_io_start(process_t *p, pthread_t *tid_epoll) + if (ret != SHIM_OK) { + return SHIM_SYS_ERR(errno); + } +- (void)sem_wait(&p->sem_mainloop); ++ while(sem_wait(&p->sem_mainloop) == -1 && errno == EINTR) { ++ continue; ++ } + (void)sem_destroy(&p->sem_mainloop); + + return SHIM_OK; +diff --git a/src/cmd/isulad/main.c b/src/cmd/isulad/main.c +index 0228caa8..7c6148fd 100644 +--- a/src/cmd/isulad/main.c ++++ b/src/cmd/isulad/main.c +@@ -1648,7 +1648,9 @@ static void *do_shutdown_handler(void *arg) + + prctl(PR_SET_NAME, "Shutdown"); + +- sem_wait(&g_daemon_shutdown_sem); ++ while(sem_wait(&g_daemon_shutdown_sem) == -1 && errno == EINTR) { ++ continue; ++ } + + daemon_shutdown(); + +@@ -1868,7 +1870,9 @@ int main(int argc, char **argv) + + server_common_start(); + +- sem_wait(&g_daemon_wait_shutdown_sem); ++ while(sem_wait(&g_daemon_wait_shutdown_sem) == -1 && errno == EINTR) { ++ continue; ++ } + + DAEMON_CLEAR_ERRMSG(); + return 0; +diff --git a/src/daemon/entry/connect/grpc/grpc_containers_service.cc b/src/daemon/entry/connect/grpc/grpc_containers_service.cc +index c5e7c275..0a46b36c 100644 +--- a/src/daemon/entry/connect/grpc/grpc_containers_service.cc ++++ b/src/daemon/entry/connect/grpc/grpc_containers_service.cc +@@ -306,7 +306,9 @@ Status ContainerServiceImpl::RemoteStart(ServerContext *context, + // close pipe 1 first, make sure io copy thread exit + close(read_pipe_fd[1]); + if (container_req->attach_stderr && ret == 0) { +- (void)sem_wait(&sem); ++ while(sem_wait(&sem) == -1 && errno == EINTR) { ++ continue; ++ } + } + (void)sem_destroy(&sem); + close(read_pipe_fd[0]); +@@ -656,7 +658,9 @@ Status ContainerServiceImpl::Attach(ServerContext *context, ServerReaderWriterattach_stderr && ret == 0) { +- (void)sem_wait(&sem_stderr); ++ while(sem_wait(&sem_stderr) == -1 && errno == EINTR) { ++ continue; ++ } + } + (void)sem_destroy(&sem_stderr); + close(pipefd[0]); +diff --git a/src/daemon/entry/cri/streams/attach_serve.cc b/src/daemon/entry/cri/streams/attach_serve.cc +index 3d59e539..9c0e56c4 100644 +--- a/src/daemon/entry/cri/streams/attach_serve.cc ++++ b/src/daemon/entry/cri/streams/attach_serve.cc +@@ -145,7 +145,9 @@ int AttachServe::ExecuteStreamCommand(SessionData *lwsCtx, void *request) + WsWriteStdoutToClient(lwsCtx, message.c_str(), message.length()); + } else { + // wait io copy thread complete +- (void)sem_wait(&attachSem); ++ while(sem_wait(&attachSem) == -1 && errno == EINTR) { ++ continue; ++ } + } + + (void)sem_destroy(&attachSem); +diff --git a/src/daemon/entry/cri/streams/websocket/ws_server.cc b/src/daemon/entry/cri/streams/websocket/ws_server.cc +index a8d89b36..7e3225b2 100644 +--- a/src/daemon/entry/cri/streams/websocket/ws_server.cc ++++ b/src/daemon/entry/cri/streams/websocket/ws_server.cc +@@ -193,7 +193,10 @@ void WebsocketServer::CloseWsSession(int socketID) + close(session->pipes.at(1)); + session->pipes.at(1) = -1; + } +- (void)sem_wait(session->syncCloseSem); ++ ++ while(sem_wait(session->syncCloseSem) == -1 && errno == EINTR) { ++ continue; ++ } + (void)sem_destroy(session->syncCloseSem); + delete session->syncCloseSem; + session->syncCloseSem = nullptr; +diff --git a/src/daemon/modules/events/collector.c b/src/daemon/modules/events/collector.c +index af688742..eb79bf81 100644 +--- a/src/daemon/modules/events/collector.c ++++ b/src/daemon/modules/events/collector.c +@@ -932,7 +932,9 @@ int add_monitor_client(char *name, const types_timestamp_t *since, const types_t + goto sem_free; + } + +- sem_wait(&context_info->context_sem); ++ while(sem_wait(&context_info->context_sem) == -1 && errno == EINTR) { ++ continue; ++ } + + sem_free: + sem_destroy(&context_info->context_sem); +@@ -1002,7 +1004,9 @@ static int start_monitored() + goto out; + } + +- sem_wait(msync.monitord_sem); ++ while(sem_wait(msync.monitord_sem) == -1 && errno == EINTR) { ++ continue; ++ } + sem_destroy(msync.monitord_sem); + if (monitored_exitcode) { + isulad_set_error_message("Monitored start failed"); +diff --git a/src/daemon/modules/service/io_handler.c b/src/daemon/modules/service/io_handler.c +index 474fa650..f3b47737 100644 +--- a/src/daemon/modules/service/io_handler.c ++++ b/src/daemon/modules/service/io_handler.c +@@ -485,7 +485,9 @@ static int start_io_copy_thread(int sync_fd, bool detach, struct io_copy_arg *co + return -1; + } + +- sem_wait(&thread_arg.wait_sem); ++ while(sem_wait(&thread_arg.wait_sem) == -1 && errno == EINTR) { ++ continue; ++ } + sem_destroy(&thread_arg.wait_sem); + return 0; + } +-- +2.34.1 + diff --git a/0147-add-no-pivot-root-support.patch b/0147-add-no-pivot-root-support.patch new file mode 100644 index 0000000000000000000000000000000000000000..6e29081ace6fad9f90e51ea96f186e5ede9b0b82 --- /dev/null +++ b/0147-add-no-pivot-root-support.patch @@ -0,0 +1,229 @@ +From 3a925ead33267d44cafd182a85e75c9c3ac25d58 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Wed, 6 Nov 2024 15:24:30 +0800 +Subject: [PATCH 147/156] add no pivot root support + +Signed-off-by: zhongtao +--- + cmake/options.cmake | 7 +++++++ + src/cmd/isula/base/create.c | 7 +++++++ + src/cmd/isula/base/create.h | 11 ++++++++++ + src/cmd/isula/base/run.c | 3 +++ + src/cmd/isula/client_arguments.h | 4 ++++ + src/cmd/isula/isula_host_spec.c | 5 +++++ + src/cmd/isula/isula_host_spec.h | 4 ++++ + src/cmd/isulad-shim/process.c | 6 ++++++ + src/daemon/modules/api/runtime_api.h | 1 + + .../modules/runtime/isula/isula_rt_ops.c | 3 +++ + .../modules/service/service_container.c | 20 +++++++++++++++++++ + 11 files changed, 71 insertions(+) + +diff --git a/cmake/options.cmake b/cmake/options.cmake +index 41177fe0..15d7044a 100644 +--- a/cmake/options.cmake ++++ b/cmake/options.cmake +@@ -168,6 +168,13 @@ if (ENABLE_NATIVE_NETWORK OR ENABLE_GRPC) + set(ENABLE_NETWORK 1) + endif() + ++option(ENABLE_NO_PIVOT_ROOT "Enable no pivot root" ON) ++if (ENABLE_NO_PIVOT_ROOT STREQUAL "ON") ++ add_definitions(-DENABLE_NO_PIVOT_ROOT) ++ set(ENABLE_NO_PIVOT_ROOT 1) ++ message("${Green}-- Enable no pivot root${ColourReset}") ++endif() ++ + option(ENABLE_PLUGIN "enable plugin module" OFF) + if (ENABLE_PLUGIN STREQUAL "ON") + add_definitions(-DENABLE_PLUGIN=1) +diff --git a/src/cmd/isula/base/create.c b/src/cmd/isula/base/create.c +index b04dddb5..7331676a 100644 +--- a/src/cmd/isula/base/create.c ++++ b/src/cmd/isula/base/create.c +@@ -1292,6 +1292,10 @@ static isula_host_config_t *request_pack_host_config(const struct client_argumen + hostconfig->publish_all = args->custom_conf.publish_all; + #endif + ++#ifdef ENABLE_NO_PIVOT_ROOT ++ hostconfig->no_pivot_root = args->custom_conf.no_pivot_root; ++#endif ++ + return hostconfig; + + error_out: +@@ -1750,6 +1754,9 @@ int cmd_create_main(int argc, const char **argv) + COMMON_OPTIONS(g_cmd_create_args) + #ifdef ENABLE_NATIVE_NETWORK + CREATE_NETWORK_OPTIONS(g_cmd_create_args) ++#endif ++#ifdef ENABLE_NO_PIVOT_ROOT ++ NO_PIVOT_ROOT_OPTIONS(g_cmd_create_args) + #endif + }; + +diff --git a/src/cmd/isula/base/create.h b/src/cmd/isula/base/create.h +index 9eb471b4..b4205a88 100644 +--- a/src/cmd/isula/base/create.h ++++ b/src/cmd/isula/base/create.h +@@ -39,6 +39,17 @@ extern "C" { + #define USERNS_OPT(cmdargs) + #endif + ++#ifdef ENABLE_NO_PIVOT_ROOT ++#define NO_PIVOT_ROOT_OPTIONS(cmdargs) \ ++ { CMD_OPT_TYPE_BOOL, \ ++ false, \ ++ "no-pivot", \ ++ 0, \ ++ &(cmdargs).custom_conf.no_pivot_root, \ ++ "disable use of pivot-root (oci runtime only)", \ ++ NULL }, ++#endif ++ + #define CREATE_OPTIONS(cmdargs) \ + { \ + CMD_OPT_TYPE_BOOL, \ +diff --git a/src/cmd/isula/base/run.c b/src/cmd/isula/base/run.c +index 8d48244c..15e035c1 100644 +--- a/src/cmd/isula/base/run.c ++++ b/src/cmd/isula/base/run.c +@@ -150,6 +150,9 @@ int cmd_run_main(int argc, const char **argv) + CREATE_EXTEND_OPTIONS(g_cmd_run_args) RUN_OPTIONS(g_cmd_run_args) + #ifdef ENABLE_NATIVE_NETWORK + CREATE_NETWORK_OPTIONS(g_cmd_run_args) ++#endif ++#ifdef ENABLE_NO_PIVOT_ROOT ++ NO_PIVOT_ROOT_OPTIONS(g_cmd_run_args) + #endif + }; + isula_libutils_default_log_config(argv[0], &lconf); +diff --git a/src/cmd/isula/client_arguments.h b/src/cmd/isula/client_arguments.h +index 76d01122..debcc903 100644 +--- a/src/cmd/isula/client_arguments.h ++++ b/src/cmd/isula/client_arguments.h +@@ -237,6 +237,10 @@ struct custom_configs { + /* publish a container's port to the host */ + char **publish; + #endif ++ ++#ifdef ENABLE_NO_PIVOT_ROOT ++ bool no_pivot_root; ++#endif + }; + + struct args_cgroup_resources { +diff --git a/src/cmd/isula/isula_host_spec.c b/src/cmd/isula/isula_host_spec.c +index 9e902ed9..4c2fefa4 100644 +--- a/src/cmd/isula/isula_host_spec.c ++++ b/src/cmd/isula/isula_host_spec.c +@@ -1729,6 +1729,11 @@ int generate_hostconfig(const isula_host_config_t *srcconfig, char **hostconfigs + #ifdef ENABLE_NATIVE_NETWORK + dstconfig->port_bindings = srcconfig->port_bindings; + #endif ++ ++#ifdef ENABLE_NO_PIVOT_ROOT ++ dstconfig->no_pivot_root = srcconfig->no_pivot_root; ++#endif ++ + *hostconfigstr = host_config_generate_json(dstconfig, &ctx, &err); + #ifdef ENABLE_NATIVE_NETWORK + dstconfig->port_bindings = NULL; +diff --git a/src/cmd/isula/isula_host_spec.h b/src/cmd/isula/isula_host_spec.h +index 25a54236..f00526e4 100644 +--- a/src/cmd/isula/isula_host_spec.h ++++ b/src/cmd/isula/isula_host_spec.h +@@ -163,6 +163,10 @@ typedef struct isula_host_config { + bool publish_all; + defs_map_string_object_port_bindings *port_bindings; + #endif ++ ++#ifdef ENABLE_NO_PIVOT_ROOT ++ bool no_pivot_root; ++#endif + } isula_host_config_t; + + int generate_hostconfig(const isula_host_config_t *srcconfig, char **hostconfigstr); +diff --git a/src/cmd/isulad-shim/process.c b/src/cmd/isulad-shim/process.c +index 11903a5c..10d21565 100644 +--- a/src/cmd/isulad-shim/process.c ++++ b/src/cmd/isulad-shim/process.c +@@ -1298,6 +1298,12 @@ static void get_runtime_cmd(process_t *p, const char *log_path, const char *pid_ + params[i++] = "create"; + params[i++] = "--bundle"; + params[i++] = p->bundle; ++#ifdef ENABLE_NO_PIVOT_ROOT ++ if (getenv("ISULAD_RAMDISK") != NULL || p->state->no_pivot_root) { ++ params[i++] = "--no-pivot"; ++ } ++#endif ++ + } + params[i++] = "--pid-file"; + params[i++] = pid_path; +diff --git a/src/daemon/modules/api/runtime_api.h b/src/daemon/modules/api/runtime_api.h +index bd170c30..930710ca 100644 +--- a/src/daemon/modules/api/runtime_api.h ++++ b/src/daemon/modules/api/runtime_api.h +@@ -84,6 +84,7 @@ typedef struct _rt_create_params_t { + bool tty; + bool open_stdin; + const char *task_addr; ++ bool no_pivot_root; + } rt_create_params_t; + + typedef struct _rt_start_params_t { +diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c +index dc156154..e628c3fe 100644 +--- a/src/daemon/modules/runtime/isula/isula_rt_ops.c ++++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c +@@ -1209,6 +1209,9 @@ int rt_isula_create(const char *id, const char *runtime, const rt_create_params_ + p.runtime_args_len = runtime_args_len; + p.attach_socket = attach_socket; + p.systemd_cgroup = conf_get_systemd_cgroup(); ++#ifdef ENABLE_NO_PIVOT_ROOT ++ p.no_pivot_root = params->no_pivot_root; ++#endif + copy_process(&p, config->process); + copy_annotations(&p, config->annotations); + +diff --git a/src/daemon/modules/service/service_container.c b/src/daemon/modules/service/service_container.c +index 4157c631..754c28ac 100644 +--- a/src/daemon/modules/service/service_container.c ++++ b/src/daemon/modules/service/service_container.c +@@ -743,6 +743,23 @@ static int do_oci_spec_update(const char *id, oci_runtime_spec *oci_spec, contai + return 0; + } + ++static bool pack_no_pivot_root(const container_t *cont) ++{ ++ size_t i = 0; ++ bool ret = false; ++ ++ ret = cont->hostconfig->no_pivot_root; ++ if (cont->common_config->config->annotations != NULL) { ++ for (i = 0; i < cont->common_config->config->annotations->len; i++) { ++ if (strcmp(cont->common_config->config->annotations->keys[i], "ISULAD_RAMDISK") == 0) { ++ ret = true; ++ break; ++ } ++ } ++ } ++ return ret; ++} ++ + static int do_start_container(container_t *cont, const char *console_fifos[], bool reset_rm, pid_ppid_info_t *pid_info) + { + int ret = 0; +@@ -906,6 +923,9 @@ static int do_start_container(container_t *cont, const char *console_fifos[], bo + create_params.exit_fifo = exit_fifo; + create_params.tty = tty; + create_params.open_stdin = open_stdin; ++#ifdef ENABLE_NO_PIVOT_ROOT ++ create_params.no_pivot_root = pack_no_pivot_root(cont); ++#endif + #ifdef ENABLE_CRI_API_V1 + if (cont->common_config->sandbox_info != NULL) { + create_params.task_addr = cont->common_config->sandbox_info->task_address; +-- +2.34.1 + diff --git a/0148-fix-issues-Isula-ps-cannot-display-port-mapping.patch b/0148-fix-issues-Isula-ps-cannot-display-port-mapping.patch new file mode 100644 index 0000000000000000000000000000000000000000..1fee14a9fb267eb2fa3d2dd280649ec623683037 --- /dev/null +++ b/0148-fix-issues-Isula-ps-cannot-display-port-mapping.patch @@ -0,0 +1,227 @@ +From 6d5121eacdb42a4dd7c2ea498c534b893b80e405 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E6=AD=A6=E7=A7=AF=E8=B6=85?= +Date: Thu, 7 Nov 2024 20:17:41 +0800 +Subject: [PATCH 148/156] fix issues: Isula ps cannot display port mapping + +--- + src/api/services/containers/container.proto | 1 + + .../connect/grpc/grpc_containers_client.cc | 2 + + src/client/connect/protocol_type.c | 4 ++ + src/client/connect/protocol_type.h | 1 + + src/cmd/isula/information/ps.c | 9 ++- + .../connect/grpc/container/list_service.cc | 3 + + src/daemon/executor/container_cb/list.c | 2 + + src/daemon/modules/api/container_api.h | 2 + + src/daemon/modules/container/container_unix.c | 56 ++++++++++++++++++- + 9 files changed, 77 insertions(+), 3 deletions(-) + +diff --git a/src/api/services/containers/container.proto b/src/api/services/containers/container.proto +index 8d05681e..113fcb10 100644 +--- a/src/api/services/containers/container.proto ++++ b/src/api/services/containers/container.proto +@@ -65,6 +65,7 @@ message Container { + string name = 16; + string health_state = 17; + int64 created = 18; ++ string ports = 19; + } + + message Container_info { +diff --git a/src/client/connect/grpc/grpc_containers_client.cc b/src/client/connect/grpc/grpc_containers_client.cc +index adeac0ba..f042290e 100644 +--- a/src/client/connect/grpc/grpc_containers_client.cc ++++ b/src/client/connect/grpc/grpc_containers_client.cc +@@ -1241,6 +1241,8 @@ private: + util_strdup_s("none"); + response->container_summary[index]->command = !in.command().empty() ? util_strdup_s(in.command().c_str()) : + util_strdup_s("-"); ++ response->container_summary[index]->ports = !in.ports().empty() ? util_strdup_s(in.ports().c_str()) : ++ nullptr; + const char *starttime = !in.startat().empty() ? in.startat().c_str() : "-"; + response->container_summary[index]->startat = util_strdup_s(starttime); + +diff --git a/src/client/connect/protocol_type.c b/src/client/connect/protocol_type.c +index 57dcf753..d0ab9732 100644 +--- a/src/client/connect/protocol_type.c ++++ b/src/client/connect/protocol_type.c +@@ -531,6 +531,10 @@ void isula_list_response_free(struct isula_list_response *response) + free(response->container_summary[i]->command); + response->container_summary[i]->command = NULL; + } ++ if (response->container_summary[i]->ports != NULL) { ++ free(response->container_summary[i]->ports); ++ response->container_summary[i]->ports = NULL; ++ } + if (response->container_summary[i]->startat != NULL) { + free(response->container_summary[i]->startat); + response->container_summary[i]->startat = NULL; +diff --git a/src/client/connect/protocol_type.h b/src/client/connect/protocol_type.h +index 2b445c5a..02e315bf 100644 +--- a/src/client/connect/protocol_type.h ++++ b/src/client/connect/protocol_type.h +@@ -204,6 +204,7 @@ struct isula_container_summary_info { + char *id; + char *image; + char *command; ++ char *ports; + char *name; + Container_Status status; + uint32_t exit_code; +diff --git a/src/cmd/isula/information/ps.c b/src/cmd/isula/information/ps.c +index 13c35dc7..6bdc157f 100644 +--- a/src/cmd/isula/information/ps.c ++++ b/src/cmd/isula/information/ps.c +@@ -332,7 +332,8 @@ static void print_basic_container_info_item(const struct isula_container_summary + } else if (strcmp(name, "Created") == 0) { + print_created_field(in->created, length->created_length); + } else if (strcmp(name, "Ports") == 0) { +- printf("%-*s", (int)length->ports_length, " "); ++ const char *ports = (in->ports != NULL ? in->ports : "N/A"); ++ printf("%-*s", (int)length->ports_length, ports); + } + } + +@@ -515,6 +516,12 @@ static void list_field_width(struct isula_container_summary_info **info, const s + l->command_length = (unsigned int)cmd_len; + } + } ++ if (in->ports != NULL) { ++ size_t ports_len = strlen(in->ports); ++ if (ports_len > l->ports_length) { ++ l->ports_length = (unsigned int)ports_len; ++ } ++ } + + calculate_str_length(in->name, &l->name_length); + calculate_str_length(in->runtime, &l->runtime_length); +diff --git a/src/daemon/entry/connect/grpc/container/list_service.cc b/src/daemon/entry/connect/grpc/container/list_service.cc +index e831acbc..dfd48191 100644 +--- a/src/daemon/entry/connect/grpc/container/list_service.cc ++++ b/src/daemon/entry/connect/grpc/container/list_service.cc +@@ -121,6 +121,9 @@ void ContainerListService::FillResponseTogRPC(void *containerRes, containers::Li + if (response->containers[i]->command != nullptr) { + container->set_command(response->containers[i]->command); + } ++ if (response->containers[i]->ports != nullptr) { ++ container->set_ports(response->containers[i]->ports); ++ } + container->set_exit_code(response->containers[i]->exit_code); + container->set_restartcount(response->containers[i]->restartcount); + if (response->containers[i]->startat != nullptr) { +diff --git a/src/daemon/executor/container_cb/list.c b/src/daemon/executor/container_cb/list.c +index 243eb4d2..2e8c7a79 100644 +--- a/src/daemon/executor/container_cb/list.c ++++ b/src/daemon/executor/container_cb/list.c +@@ -609,6 +609,8 @@ static int fill_container_info(container_container *container_info, const contai + + container_info->status = (int)container_state_judge_status(cont_state); + ++ container_info->ports = container_get_ports(cont); ++ + container_info->command = container_get_command(cont); + image = container_get_image(cont); + container_info->image = image ? image : util_strdup_s("none"); +diff --git a/src/daemon/modules/api/container_api.h b/src/daemon/modules/api/container_api.h +index a6ec8e22..e4d7fc25 100644 +--- a/src/daemon/modules/api/container_api.h ++++ b/src/daemon/modules/api/container_api.h +@@ -185,6 +185,8 @@ int container_v2_spec_merge_container_spec(container_config_v2_common_config *v2 + + char *container_get_command(const container_t *cont); + ++char *container_get_ports(const container_t *cont); ++ + char *container_get_image(const container_t *cont); + + int container_exit_on_next(container_t *cont); +diff --git a/src/daemon/modules/container/container_unix.c b/src/daemon/modules/container/container_unix.c +index 6f345ea0..812ab9e1 100644 +--- a/src/daemon/modules/container/container_unix.c ++++ b/src/daemon/modules/container/container_unix.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -1253,7 +1254,7 @@ char *container_get_command(const container_t *cont) + if (cont->common_config->path != NULL) { + nret = util_array_append(&args, cont->common_config->path); + if (nret < 0) { +- ERROR("Appned string failed"); ++ ERROR("Append string failed"); + goto cleanup; + } + } +@@ -1268,7 +1269,7 @@ char *container_get_command(const container_t *cont) + nret = util_array_append(&args, arg); + free(arg); + if (nret < 0) { +- ERROR("Appned string failed"); ++ ERROR("Append string failed"); + goto cleanup; + } + } +@@ -1280,6 +1281,57 @@ cleanup: + return cmd; + } + ++/* container get ports */ ++char *container_get_ports(const container_t *cont) ++{ ++ int nret; ++ size_t i, j, ports_num = 0; ++ __isula_auto_array_t char **args = NULL; ++ char *ports = NULL; ++ ++ if (cont == NULL || cont->hostconfig == NULL || cont->hostconfig->port_bindings == NULL) { ++ return NULL; ++ } ++ ++ for (i = 0; cont->hostconfig->port_bindings->keys != NULL && i < cont->hostconfig->port_bindings->len; i++) { ++ for (j = 0; j < cont->hostconfig->port_bindings->values[i]->element->host_len; j++) { ++ __isula_auto_free char *arg = NULL; ++ char *host_ip = cont->hostconfig->port_bindings->values[i]->element->host[j]->host_ip; ++ if (host_ip == NULL) { ++ host_ip = "0.0.0.0"; ++ } ++ char *host_port = cont->hostconfig->port_bindings->values[i]->element->host[j]->host_port; ++ if (host_port == NULL) { ++ host_port = ""; ++ } ++ char *cont_port_type = cont->hostconfig->port_bindings->keys[i]; ++ if (cont_port_type == NULL) { ++ cont_port_type = ""; ++ } ++ size_t total_len = strlen(host_ip) + strlen(host_port) + strlen(cont_port_type) + 4; // 4 for ":->" and null terminator ++ arg = util_common_calloc_s(total_len); ++ if (arg == NULL) { ++ ERROR("Out of memory"); ++ return ports; ++ } ++ nret = snprintf(arg, total_len, "%s:%s->%s", host_ip, host_port, cont_port_type); ++ if (nret < 0 || (size_t)nret >= total_len) { ++ ERROR("Failed to print string"); ++ return ports; ++ } ++ nret = util_array_append(&args, arg); ++ if (nret < 0) { ++ ERROR("Append string failed"); ++ return ports; ++ } ++ ports_num++; ++ } ++ } ++ ports = util_string_join(", ", (const char **)args, ports_num); ++ ++ return ports; ++} ++ + /* container get image */ + char *container_get_image(const container_t *cont) + { +-- +2.34.1 + diff --git a/0149-move-nri-call-in-stop-and-remove-con.patch b/0149-move-nri-call-in-stop-and-remove-con.patch new file mode 100644 index 0000000000000000000000000000000000000000..8c73f2d504dee0ae330a019ec001c963307653c9 --- /dev/null +++ b/0149-move-nri-call-in-stop-and-remove-con.patch @@ -0,0 +1,87 @@ +From db60c64138b45539fe70282c853ac2dae5954924 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Thu, 14 Nov 2024 17:34:49 +0800 +Subject: [PATCH 149/156] move nri call in stop and remove con + +Signed-off-by: zhongtao +--- + src/daemon/common/cri/cri_helpers.cc | 18 ++++++++++++++++++ + .../cri/v1/v1_cri_container_manager_service.cc | 14 -------------- + 2 files changed, 18 insertions(+), 14 deletions(-) + +diff --git a/src/daemon/common/cri/cri_helpers.cc b/src/daemon/common/cri/cri_helpers.cc +index a8cbd996..aa8e3c19 100644 +--- a/src/daemon/common/cri/cri_helpers.cc ++++ b/src/daemon/common/cri/cri_helpers.cc +@@ -32,6 +32,10 @@ + #include "isulad_config.h" + #include "sha256.h" + ++#ifdef ENABLE_NRI ++#include "nri_adaption.h" ++#endif ++ + namespace CRIHelpers { + const std::string Constants::POD_NETWORK_ANNOTATION_KEY { "network.alpha.kubernetes.io/network" }; + const std::string Constants::CONTAINER_TYPE_LABEL_KEY { "cri.isulad.type" }; +@@ -660,6 +664,13 @@ void RemoveContainerHelper(service_executor_t *cb, const std::string &containerI + goto cleanup; + } + ++#ifdef ENABLE_NRI ++ if (!NRIAdaptation::GetInstance()->RemoveContainer(containerID, error)) { ++ ERROR("NRI RemoveContainer notification failed: %s", error.GetCMessage()); ++ } ++ error.Clear(); ++#endif ++ + if (cb->container.remove(request, &response) != 0) { + if (response != nullptr && response->errmsg != nullptr) { + error.SetError(response->errmsg); +@@ -719,6 +730,13 @@ void StopContainerHelper(service_executor_t *cb, const std::string &containerID, + error.SetError(msg); + } + ++#ifdef ENABLE_NRI ++ if (!NRIAdaptation::GetInstance()->StopContainer(containerID, error)) { ++ ERROR("NRI StopContainer notification failed: %s", error.GetCMessage()); ++ } ++ error.Clear(); ++#endif ++ + free_container_stop_request(request); + free_container_stop_response(response); + } +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 1e84d14c..b585b49c 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 +@@ -618,25 +618,11 @@ cleanup: + + void ContainerManagerService::StopContainer(const std::string &containerID, int64_t timeout, Errors &error) + { +-#ifdef ENABLE_NRI +- Errors nriErr; +-#endif + CRIHelpers::StopContainer(m_cb, containerID, timeout, error); +-#ifdef ENABLE_NRI +- if (!NRIAdaptation::GetInstance()->StopContainer(containerID, nriErr)) { +- ERROR("NRI StopContainer notification failed: %s", nriErr.GetCMessage()); +- } +-#endif + } + + void ContainerManagerService::RemoveContainer(const std::string &containerID, Errors &error) + { +-#ifdef ENABLE_NRI +- Errors nriErr; +- if (!NRIAdaptation::GetInstance()->RemoveContainer(containerID, nriErr)) { +- ERROR("NRI RemoveContainer notification failed: %s", nriErr.GetCMessage()); +- } +-#endif + CRIHelpers::RemoveContainer(m_cb, containerID, error); + if (error.NotEmpty()) { + WARN("Failed to remove container %s", containerID.c_str()); +-- +2.34.1 + diff --git a/0150-add-missing-con-linux-info-for-nri-module.patch b/0150-add-missing-con-linux-info-for-nri-module.patch new file mode 100644 index 0000000000000000000000000000000000000000..771719341382cd5258da313e46c5fb5e510b37a3 --- /dev/null +++ b/0150-add-missing-con-linux-info-for-nri-module.patch @@ -0,0 +1,548 @@ +From 140166e0f385a2f23502efeeba4113536736c3c8 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Thu, 14 Nov 2024 16:45:08 +0800 +Subject: [PATCH 150/156] add missing con linux info for nri module + +Signed-off-by: zhongtao +--- + src/daemon/common/nri/nri_convert.cc | 482 ++++++++++++++++++++++++++- + 1 file changed, 480 insertions(+), 2 deletions(-) + +diff --git a/src/daemon/common/nri/nri_convert.cc b/src/daemon/common/nri/nri_convert.cc +index 30caf1dd..d862d992 100644 +--- a/src/daemon/common/nri/nri_convert.cc ++++ b/src/daemon/common/nri/nri_convert.cc +@@ -15,12 +15,16 @@ + + #include "nri_convert.h" + ++#include ++#include ++ + #include "container_api.h" + #include "v1_cri_helpers.h" + #include "path.h" + #include "transform.h" + #include "nri_utils.h" + #include "cstruct_wrapper.h" ++#include "specs_api.h" + + static int64_t DefaultOOMScoreAdj = 0; + +@@ -385,6 +389,462 @@ error_out: + return false; + } + ++static int ConvertDevice(const char *host_path, const char *container_path, const char *permissions, ++ nri_linux_device &device, nri_linux_device_cgroup &deviceCgroup) ++{ ++ int ret = 0; ++ struct stat st; ++ const char *dev_type = NULL; ++ unsigned int file_mode = 0; ++ ++ if (host_path == NULL) { ++ return -1; ++ } ++ ++ ret = stat(host_path, &st); ++ if (ret < 0) { ++ ERROR("device %s no exists", host_path); ++ return -1; ++ } ++ ++ file_mode = st.st_mode & 0777; ++ ++ /* check device type first */ ++ if (S_ISBLK(st.st_mode)) { ++ file_mode |= S_IFBLK; ++ dev_type = "b"; ++ } else if (S_ISCHR(st.st_mode)) { ++ file_mode |= S_IFCHR; ++ dev_type = "c"; ++ } else { ++ ERROR("Cannot determine the device number for device %s", host_path); ++ return -1; ++ } ++ ++ /* fill spec dev */ ++ device.major = (int64_t)major(st.st_rdev); ++ device.minor = (int64_t)minor(st.st_rdev); ++ device.uid = (uint32_t *)util_common_calloc_s(sizeof(uint32_t*)); ++ if (device.uid == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ *(device.uid) = st.st_uid; ++ device.gid = (uint32_t *)util_common_calloc_s(sizeof(uint32_t*)); ++ if (device.gid == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ *(device.gid) = st.st_gid; ++ device.file_mode = (uint32_t *)util_common_calloc_s(sizeof(uint32_t)); ++ if (device.file_mode == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ *(device.file_mode) = (int)file_mode; ++ device.type = util_strdup_s(dev_type); ++ device.path = util_strdup_s(container_path); ++ ++ /* fill spec cgroup dev */ ++ deviceCgroup.allow = true; ++ deviceCgroup.access = util_strdup_s(permissions); ++ deviceCgroup.type = util_strdup_s(dev_type); ++ deviceCgroup.major = (int64_t *)util_common_calloc_s(sizeof(int64_t)); ++ if (deviceCgroup.major == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ *(deviceCgroup.major) = (int64_t)major(st.st_rdev); ++ deviceCgroup.minor = (int64_t *)util_common_calloc_s(sizeof(int64_t)); ++ if (deviceCgroup.minor == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ *(deviceCgroup.minor) = (int64_t)minor(st.st_rdev); ++ ++ return 0; ++} ++ ++static int ConvertHostConfigDevices(const host_config_devices_element *dev_map, nri_linux_device &device, ++ nri_linux_device_cgroup &deviceCgroup) ++{ ++ return ConvertDevice(dev_map->path_on_host, dev_map->path_in_container, ++ dev_map->cgroup_permissions, device, deviceCgroup); ++} ++ ++static int ConLinuxDeviceToNRI(const host_config *config, nri_container &con) ++{ ++ size_t i; ++ ++ if (config->devices_len == 0 && config->nri_devices_len == 0) { ++ return 0; ++ } ++ con.linux->devices = (nri_linux_device **)util_smart_calloc_s(sizeof(nri_linux_device *), ++ config->devices_len + config->nri_devices_len); ++ if (con.linux->devices == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ ++ con.linux->resources->devices = (nri_linux_device_cgroup **)util_smart_calloc_s(sizeof(nri_linux_device_cgroup *), ++ config->devices_len); ++ if (con.linux->resources->devices == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ ++ for (i = 0; i < config->devices_len; i++) { ++ nri_linux_device *device = (nri_linux_device *)util_common_calloc_s(sizeof(nri_linux_device)); ++ if (device == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ ++ nri_linux_device_cgroup *deviceCgroup = (nri_linux_device_cgroup *)util_common_calloc_s(sizeof( ++ nri_linux_device_cgroup)); ++ if (deviceCgroup == nullptr) { ++ ERROR("Out of memory"); ++ free_nri_linux_device(device); ++ return -1; ++ } ++ ++ if (ConvertHostConfigDevices(config->devices[i], *device, *deviceCgroup) != 0) { ++ ERROR("Failed to convert host config devices"); ++ free_nri_linux_device(device); ++ free_nri_linux_device_cgroup(deviceCgroup); ++ return -1; ++ } ++ ++ con.linux->devices[i] = device; ++ con.linux->resources->devices[i] = deviceCgroup; ++ con.linux->devices_len++; ++ con.linux->resources->devices_len++; ++ } ++ ++ for (i = 0; i < config->nri_devices_len; i++) { ++ nri_linux_device *device = (nri_linux_device *)util_common_calloc_s(sizeof(nri_linux_device)); ++ if (device == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ ++ device->file_mode = (uint32_t *)util_common_calloc_s(sizeof(uint32_t)); ++ if (device->file_mode == nullptr) { ++ ERROR("Out of memory"); ++ free_nri_linux_device(device); ++ return -1; ++ } ++ *(device->file_mode) = config->nri_devices[i]->file_mode; ++ ++ device->path = util_strdup_s(config->nri_devices[i]->path); ++ device->type = util_strdup_s(config->nri_devices[i]->type); ++ device->major = config->nri_devices[i]->major; ++ device->minor = config->nri_devices[i]->minor; ++ ++ device->uid = (uint32_t *)util_common_calloc_s(sizeof(uint32_t)); ++ if (device->uid == nullptr) { ++ ERROR("Out of memory"); ++ free_nri_linux_device(device); ++ return -1; ++ } ++ *(device->uid) = config->nri_devices[i]->uid; ++ ++ device->gid = (uint32_t *)util_common_calloc_s(sizeof(uint32_t)); ++ if (device->gid == nullptr) { ++ ERROR("Out of memory"); ++ free_nri_linux_device(device); ++ return -1; ++ } ++ *(device->gid) = config->nri_devices[i]->gid; ++ con.linux->devices[i + config->devices_len] = device; ++ con.linux->devices_len++; ++ } ++ ++ return 0; ++} ++ ++static int ConvertCRIV1Devices(const ::runtime::v1::Device &dev_map, nri_linux_device &device, ++ nri_linux_device_cgroup &deviceCgroup) ++{ ++ return ConvertDevice(dev_map.host_path().c_str(), dev_map.container_path().c_str(), ++ dev_map.permissions().c_str(), device, deviceCgroup); ++} ++ ++static bool ConLinuxResourcesCpuToNRI(const host_config *config, nri_linux_cpu &cpu) ++{ ++ cpu.shares = (uint64_t *)util_common_calloc_s(sizeof(uint64_t)); ++ if (cpu.shares == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ *(cpu.shares) = config->cpu_shares; ++ ++ cpu.quota = (int64_t *)util_common_calloc_s(sizeof(int64_t)); ++ if (cpu.quota == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ *(cpu.quota) = config->cpu_quota; ++ ++ cpu.period = (uint64_t *)util_common_calloc_s(sizeof(uint64_t)); ++ if (cpu.period == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ *(cpu.period) = config->cpu_period; ++ ++ cpu.cpus = util_strdup_s(config->cpuset_cpus); ++ cpu.mems = util_strdup_s(config->cpuset_mems); ++ ++ return true; ++} ++ ++static bool ConLinuxResourcesMemoryToNRI(const host_config *config, nri_linux_memory &memory) ++{ ++ memory.limit = (int64_t *)util_common_calloc_s(sizeof(int64_t)); ++ if (memory.limit == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ *(memory.limit) = config->memory; ++ ++ memory.reservation = (int64_t *)util_common_calloc_s(sizeof(int64_t)); ++ if (memory.reservation == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ ++ *(memory.reservation) = config->memory_reservation; ++ ++ memory.swap = (int64_t *)util_common_calloc_s(sizeof(int64_t)); ++ if (memory.swap == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ *(memory.swap) = config->memory_swap; ++ ++ memory.kernel = (int64_t *)util_common_calloc_s(sizeof(int64_t)); ++ if (memory.kernel == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ *(memory.kernel) = config->kernel_memory; ++ ++ // isulad has not set kernel_tcp ++ memory.kernel_tcp = nullptr; ++ ++ if (config->memory_swappiness != nullptr) { ++ memory.swappiness = (uint64_t *)util_common_calloc_s(sizeof(uint64_t)); ++ if (memory.swappiness == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ *(memory.swappiness) = *(config->memory_swappiness); ++ } ++ ++ memory.disable_oom_killer = (uint8_t *)util_common_calloc_s(sizeof(uint8_t)); ++ if (memory.disable_oom_killer == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ *(memory.disable_oom_killer) = config->oom_kill_disable; ++ ++ // isulad has not set use_hierarchy ++ memory.use_hierarchy = (uint8_t *)util_common_calloc_s(sizeof(uint8_t)); ++ if (memory.use_hierarchy == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ *(memory.use_hierarchy) = false; ++ return true; ++} ++ ++auto ConLinuxResourcesToNRI(const host_config *config) -> nri_linux_resources * ++{ ++ nri_linux_resources *resources = nullptr; ++ size_t i; ++ ++ resources = init_nri_linux_resources(); ++ if (resources == nullptr) { ++ ERROR("Failed to init nri linux resources"); ++ return nullptr; ++ } ++ ++ if (!ConLinuxResourcesCpuToNRI(config, *resources->cpu)) { ++ ERROR("Failed to transform cpu to nri"); ++ goto error_out; ++ } ++ ++ if (!ConLinuxResourcesMemoryToNRI(config, *resources->memory)) { ++ ERROR("Failed to transform memory to nri"); ++ goto error_out; ++ } ++ ++ resources->hugepage_limits = (nri_hugepage_limit **)util_smart_calloc_s(sizeof(nri_hugepage_limit *), ++ config->hugetlbs_len); ++ if (resources->hugepage_limits == nullptr) { ++ ERROR("Out of memory"); ++ goto error_out; ++ } ++ ++ for (i = 0; i < config->hugetlbs_len; i++) { ++ resources->hugepage_limits[i] = (nri_hugepage_limit *)util_common_calloc_s(sizeof(nri_hugepage_limit)); ++ if (resources->hugepage_limits[i] == nullptr) { ++ ERROR("Out of memory"); ++ goto error_out; ++ } ++ resources->hugepage_limits[i]->page_size = util_strdup_s(config->hugetlbs[i]->page_size); ++ resources->hugepage_limits[i]->limit = config->hugetlbs[i]->limit; ++ resources->hugepage_limits_len++; ++ } ++ ++ // resources.blockio_class is not support ++ // resources.rdt_class is not support ++ // They are not standard fields in oci spec ++ ++ if (dup_json_map_string_string(config->unified, resources->unified) != 0) { ++ ERROR("Failed to copy unified map"); ++ goto error_out; ++ } ++ ++ // resources.devices is set in ConLinuxDeviceToNRI ++ ++ return resources; ++ ++error_out: ++ free_nri_linux_resources(resources); ++ resources = nullptr; ++ return resources; ++} ++ ++static bool ConLinuxToNRI(const char *id, const host_config *config, nri_container &con) ++{ ++ con.linux = (nri_linux_container *)util_common_calloc_s(sizeof(nri_linux_container)); ++ if (con.linux == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ ++ con.linux->resources = ConLinuxResourcesToNRI(config); ++ if (con.linux->resources == nullptr) { ++ ERROR("Failed to transform resources to nri for con : %s", id); ++ return false; ++ } ++ ++ if (ConLinuxDeviceToNRI(config, con) != 0) { ++ ERROR("Failed to transform devices to nri for con : %s", id); ++ return false; ++ } ++ ++ con.linux->oom_score_adj = (int64_t *)util_common_calloc_s(sizeof(int64_t)); ++ if (con.linux->oom_score_adj == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ ++ *(con.linux->oom_score_adj) = config->oom_score_adj; ++ ++ con.linux->cgroups_path = merge_container_cgroups_path(id, config); ++ if (con.linux->cgroups_path == NULL) { ++ WARN("nri container cgroups path is NULL"); ++ } ++ return true; ++} ++ ++static int ConConfigLinuxDeviceToNRI(const runtime::v1::ContainerConfig &containerConfig, nri_container &con) ++{ ++ int i; ++ int conConfigDevicesSize = containerConfig.devices_size(); ++ ++ if (conConfigDevicesSize == 0) { ++ return 0; ++ } ++ con.linux->devices = (nri_linux_device **)util_smart_calloc_s(sizeof(nri_linux_device *), conConfigDevicesSize); ++ if (con.linux->devices == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ ++ if (con.linux->resources == nullptr) { ++ con.linux->resources = init_nri_linux_resources(); ++ if (con.linux->resources == nullptr) { ++ ERROR("Failed to init nri linux resources"); ++ return -1; ++ } ++ } ++ ++ con.linux->resources->devices = (nri_linux_device_cgroup **)util_smart_calloc_s(sizeof(nri_linux_device_cgroup *), ++ conConfigDevicesSize); ++ if (con.linux->resources->devices == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ ++ for (i = 0; i < conConfigDevicesSize; i++) { ++ nri_linux_device *device = (nri_linux_device *)util_common_calloc_s(sizeof(nri_linux_device)); ++ if (device == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ ++ nri_linux_device_cgroup *deviceCgroup = (nri_linux_device_cgroup *)util_common_calloc_s(sizeof( ++ nri_linux_device_cgroup)); ++ if (deviceCgroup == nullptr) { ++ ERROR("Out of memory"); ++ free_nri_linux_device(device); ++ return -1; ++ } ++ ++ if (ConvertCRIV1Devices(containerConfig.devices(i), *device, *deviceCgroup) != 0) { ++ ERROR("Failed to convert CRI v1 devices"); ++ free_nri_linux_device(device); ++ free_nri_linux_device_cgroup(deviceCgroup); ++ return -1; ++ } ++ ++ con.linux->devices[i] = device; ++ con.linux->resources->devices[i] = deviceCgroup; ++ con.linux->devices_len++; ++ con.linux->resources->devices_len++; ++ } ++ ++ return 0; ++} ++ ++static bool ConConfigLinuxToNRI(const runtime::v1::ContainerConfig &containerConfig, nri_container &con) ++{ ++ const char *name = containerConfig.metadata().name().c_str(); ++ con.linux = (nri_linux_container *)util_common_calloc_s(sizeof(nri_linux_container)); ++ if (con.linux == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ ++ if (containerConfig.has_linux() && containerConfig.linux().has_resources()) { ++ con.linux->resources = LinuxResourcesToNRI(containerConfig.linux().resources()); ++ if (con.linux->resources == nullptr) { ++ ERROR("Failed to transform resources to nri for con : %s", name); ++ return false; ++ } ++ ++ con.linux->oom_score_adj = (int64_t *)util_common_calloc_s(sizeof(int64_t)); ++ if (con.linux->oom_score_adj == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ *(con.linux->oom_score_adj) = containerConfig.linux().resources().oom_score_adj(); ++ } ++ ++ if (ConConfigLinuxDeviceToNRI(containerConfig, con) != 0) { ++ ERROR("Failed to convert devices to nri for con : %s", name); ++ return false; ++ } ++ ++ // ContainerToNRIByConfig is called when CreateContainer, and cannot get pid at this time ++ con.linux->cgroups_path = NULL; ++ return true; ++} ++ + // container info is incomplete because container in excution is not created + auto ContainerToNRIByConConfig(const runtime::v1::ContainerConfig &containerConfig, nri_container &con) -> bool + { +@@ -395,6 +855,9 @@ auto ContainerToNRIByConConfig(const runtime::v1::ContainerConfig &containerConf + + Errors tmpError; + ++ // ContainerToNRIByConfig is called when CreateConatiner, and the status is 0(CONTAINER_UNKNOWN) at this time ++ con.state = 0; ++ + con.labels = Transform::ProtobufMapToJsonMapForString(containerConfig.labels(), tmpError); + if (con.labels == nullptr) { + ERROR("Failed to transform labels to nri for con : %s, : %s", con.name, tmpError.GetMessage().c_str()); +@@ -426,9 +889,18 @@ auto ContainerToNRIByConConfig(const runtime::v1::ContainerConfig &containerConf + ERROR("Failed to transform mounts to nri for con : %s", con.name); + return false; + } +- return true; + +- // todo: can not get container hooks and pid from containerConfig ++ if (!ConConfigLinuxToNRI(containerConfig, con)) { ++ ERROR("Failed to convert conatiner linux info to nri for con : %s", con.name); ++ return false; ++ } ++ ++ // todo: CRI module can not get container hooks from containerConfig ++ // ContainerToNRIByConfig is called when CreateConatiner, and cannot get pid at this time ++ ++ // rlimit not support in containerd ++ ++ return true; + } + + // container info is incomplete because container in excution is not created +@@ -486,6 +958,11 @@ auto ContainerToNRIByID(const std::string &id, nri_container &con) -> bool + goto out; + } + ++ if (!ConLinuxToNRI(cont->common_config->id, cont->hostconfig, con)) { ++ ERROR("Failed to transform conatiner linux info to nri for con : %s", con.name); ++ goto out; ++ } ++ + // todo: can convert hostconfig's hook_spec to nri spec + + con.pid = container_state_get_pid(cont->state); +@@ -644,6 +1121,7 @@ auto ContainersToNRI(std::vector> &conta + } + if (!ContainerToNRIByID(containers[i].get()->id(), *con)) { + ERROR("Failed to transform container to nri for container : %s", containers[i]->metadata().name().c_str()); ++ free_nri_container(con); + return false; + } + cons.push_back(con); +-- +2.34.1 + diff --git a/0151-sandbox-sandbox-api-update.patch b/0151-sandbox-sandbox-api-update.patch new file mode 100644 index 0000000000000000000000000000000000000000..f925cccf57576d300ac9ee9f9132ef8763af781e --- /dev/null +++ b/0151-sandbox-sandbox-api-update.patch @@ -0,0 +1,1600 @@ +From b994e99a4188bef549e5fa1f944eb3546be43201 Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Wed, 18 Sep 2024 11:40:15 +0800 +Subject: [PATCH 151/156] sandbox:sandbox api update + +Signed-off-by: liuxu +--- + cmake/protoc.cmake | 1 + + src/api/services/sandbox/sandbox.proto | 107 +++--- + .../sandbox/sandbox/types/metrics.proto | 30 ++ + .../sandbox/sandbox/types/platform.proto | 3 +- + .../sandbox/sandbox/types/sandbox.proto | 15 +- + src/daemon/sandbox/controller/controller.h | 12 +- + .../sandboxer/client/grpc_sandboxer_client.cc | 111 ++---- + .../sandboxer/client/grpc_sandboxer_client.h | 18 +- + .../sandboxer/sandboxer_controller.cc | 19 +- + .../sandboxer/sandboxer_controller.h | 9 +- + .../controller/shim/shim_controller.cc | 11 +- + .../sandbox/controller/shim/shim_controller.h | 9 +- + src/daemon/sandbox/sandbox.cc | 221 +++++++++++- + src/daemon/sandbox/sandbox.h | 24 ++ + src/daemon/sandbox/sandbox_ops.cc | 333 ++++++++++++++---- + src/daemon/sandbox/sandbox_task.cc | 99 ++++++ + src/daemon/sandbox/sandbox_task.h | 48 +++ + 17 files changed, 808 insertions(+), 262 deletions(-) + create mode 100644 src/api/services/sandbox/sandbox/types/metrics.proto + create mode 100644 src/daemon/sandbox/sandbox_task.cc + create mode 100644 src/daemon/sandbox/sandbox_task.h + +diff --git a/cmake/protoc.cmake b/cmake/protoc.cmake +index 6e2d1b84..6343fe3e 100644 +--- a/cmake/protoc.cmake ++++ b/cmake/protoc.cmake +@@ -72,6 +72,7 @@ if (ENABLE_CRI_API_V1 AND ENABLE_SANDBOXER) + PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox/types/sandbox.proto) + PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox/types/mount.proto) + PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox/types/platform.proto) ++ PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox/types/metrics.proto) + PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox.proto) + PROTOC_GRPC_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox.proto) + endif() +diff --git a/src/api/services/sandbox/sandbox.proto b/src/api/services/sandbox/sandbox.proto +index 87c7e27c..dcc78444 100644 +--- a/src/api/services/sandbox/sandbox.proto ++++ b/src/api/services/sandbox/sandbox.proto +@@ -31,6 +31,7 @@ import "google/protobuf/timestamp.proto"; + import "sandbox/types/sandbox.proto"; + import "sandbox/types/mount.proto"; + import "sandbox/types/platform.proto"; ++import "sandbox/types/metrics.proto"; + + option go_package = "github.com/containerd/containerd/api/services/sandbox/v1;sandbox"; + +@@ -89,21 +90,22 @@ service Controller { + rpc Create(ControllerCreateRequest) returns (ControllerCreateResponse); + rpc Start(ControllerStartRequest) returns (ControllerStartResponse); + rpc Platform(ControllerPlatformRequest) returns (ControllerPlatformResponse); +- rpc Prepare(PrepareRequest) returns (PrepareResponse); +- rpc Purge(PurgeRequest) returns (PurgeResponse); +- rpc UpdateResources(UpdateResourcesRequest) returns (UpdateResourcesResponse); + rpc Stop(ControllerStopRequest) returns (ControllerStopResponse); + rpc Wait(ControllerWaitRequest) returns (ControllerWaitResponse); + rpc Status(ControllerStatusRequest) returns (ControllerStatusResponse); + rpc Shutdown(ControllerShutdownRequest) returns (ControllerShutdownResponse); ++ rpc Metrics(ControllerMetricsRequest) returns (ControllerMetricsResponse); ++ rpc Update(ControllerUpdateRequest) returns (ControllerUpdateResponse); + } + + message ControllerCreateRequest { +- string sandboxer = 1; +- string sandbox_id = 2; +- repeated containerd.types.Mount rootfs = 3; +- google.protobuf.Any options = 4; +- string netns_path = 5; ++ string sandbox_id = 1; ++ repeated containerd.types.Mount rootfs = 2; ++ google.protobuf.Any options = 3; ++ string netns_path = 4; ++ map annotations = 5; ++ containerd.types.Sandbox sandbox = 6; ++ string sandboxer = 10; + } + + message ControllerCreateResponse { +@@ -111,8 +113,8 @@ message ControllerCreateResponse { + } + + message ControllerStartRequest { +- string sandboxer = 1; +- string sandbox_id = 2; ++ string sandbox_id = 1; ++ string sandboxer = 10; + } + + message ControllerStartResponse { +@@ -120,12 +122,16 @@ message ControllerStartResponse { + uint32 pid = 2; + google.protobuf.Timestamp created_at = 3; + map labels = 4; +- string task_address = 5; ++ // Address of the sandbox for containerd to connect, ++ // for calling Task or other APIs serving in the sandbox. ++ // it is in the form of ttrpc+unix://path/to/uds or grpc+vsock://:. ++ string address = 5; ++ uint32 version = 6; + } + + message ControllerPlatformRequest { +- string sandboxer = 1; +- string sandbox_id = 2; ++ string sandbox_id = 1; ++ string sandboxer = 10; + } + + message ControllerPlatformResponse { +@@ -133,16 +139,16 @@ message ControllerPlatformResponse { + } + + message ControllerStopRequest { +- string sandboxer = 1; +- string sandbox_id = 2; +- uint32 timeout_secs = 3; ++ string sandbox_id = 1; ++ uint32 timeout_secs = 2; ++ string sandboxer = 10; + } + + message ControllerStopResponse {} + + message ControllerWaitRequest { +- string sandboxer = 1; +- string sandbox_id = 2; ++ string sandbox_id = 1; ++ string sandboxer = 10; + } + + message ControllerWaitResponse { +@@ -151,61 +157,48 @@ message ControllerWaitResponse { + } + + message ControllerStatusRequest { +- string sandboxer = 1; +- string sandbox_id = 2; +- bool verbose = 3; ++ string sandbox_id = 1; ++ bool verbose = 2; ++ string sandboxer = 10; + } + + message ControllerStatusResponse { + string sandbox_id = 1; + uint32 pid = 2; + string state = 3; +- string task_address = 4; +- map info = 5; +- google.protobuf.Timestamp created_at = 6; +- google.protobuf.Timestamp exited_at = 7; +- google.protobuf.Any extra = 8; ++ map info = 4; ++ google.protobuf.Timestamp created_at = 5; ++ google.protobuf.Timestamp exited_at = 6; ++ google.protobuf.Any extra = 7; ++ // Address of the sandbox for containerd to connect, ++ // for calling Task or other APIs serving in the sandbox. ++ // it is in the form of ttrpc+unix://path/to/uds or grpc+vsock://:. ++ string address = 8; ++ uint32 version = 9; + } + + message ControllerShutdownRequest { +- string sandboxer = 1; +- string sandbox_id = 2; ++ string sandbox_id = 1; ++ string sandboxer = 10; + } + + message ControllerShutdownResponse {} + +-message PrepareRequest { +- string sandboxer = 1; +- string sandbox_id = 2; +- string container_id = 3; +- string exec_id = 4; +- google.protobuf.Any spec = 5; +- repeated containerd.types.Mount rootfs = 6; +- string stdin = 7; +- string stdout = 8; +- string stderr = 9; +- bool terminal = 10; +-} +- +-message PrepareResponse { +- string bundle = 1; ++message ControllerMetricsRequest { ++ string sandbox_id = 1; ++ string sandboxer = 10; + } + +-message PurgeRequest { +- string sandboxer = 1; +- string sandbox_id = 2; +- string container_id = 3; +- string exec_id = 4; ++message ControllerMetricsResponse { ++ types.Metric metrics = 1; + } + +-message PurgeResponse {} +- +-message UpdateResourcesRequest { +- string sandboxer = 1; +- string sandbox_id = 2; +- string container_id = 3; +- google.protobuf.Any resources = 4; +- map annotations = 5; ++message ControllerUpdateRequest { ++ string sandbox_id = 1; ++ string sandboxer = 2; ++ containerd.types.Sandbox sandbox = 3; ++ repeated string fields = 4; + } + +-message UpdateResourcesResponse {} ++message ControllerUpdateResponse { ++} +\ No newline at end of file +diff --git a/src/api/services/sandbox/sandbox/types/metrics.proto b/src/api/services/sandbox/sandbox/types/metrics.proto +new file mode 100644 +index 00000000..61185939 +--- /dev/null ++++ b/src/api/services/sandbox/sandbox/types/metrics.proto +@@ -0,0 +1,30 @@ ++/* ++ Copyright The containerd Authors. ++ ++ Licensed under the Apache License, Version 2.0 (the "License"); ++ you may not use this file except in compliance with the License. ++ You may obtain a copy of the License at ++ ++ http://www.apache.org/licenses/LICENSE-2.0 ++ ++ Unless required by applicable law or agreed to in writing, software ++ distributed under the License is distributed on an "AS IS" BASIS, ++ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ See the License for the specific language governing permissions and ++ limitations under the License. ++*/ ++ ++syntax = "proto3"; ++ ++package containerd.types; ++ ++import "google/protobuf/any.proto"; ++import "google/protobuf/timestamp.proto"; ++ ++option go_package = "github.com/containerd/containerd/api/types;types"; ++ ++message Metric { ++ google.protobuf.Timestamp timestamp = 1; ++ string id = 2; ++ google.protobuf.Any data = 3; ++} +\ No newline at end of file +diff --git a/src/api/services/sandbox/sandbox/types/platform.proto b/src/api/services/sandbox/sandbox/types/platform.proto +index b6088251..102e6e2b 100644 +--- a/src/api/services/sandbox/sandbox/types/platform.proto ++++ b/src/api/services/sandbox/sandbox/types/platform.proto +@@ -26,4 +26,5 @@ message Platform { + string os = 1; + string architecture = 2; + string variant = 3; +-} ++ string os_version = 4; ++} +\ No newline at end of file +diff --git a/src/api/services/sandbox/sandbox/types/sandbox.proto b/src/api/services/sandbox/sandbox/types/sandbox.proto +index 7b9d196b..6fe08d40 100644 +--- a/src/api/services/sandbox/sandbox/types/sandbox.proto ++++ b/src/api/services/sandbox/sandbox/types/sandbox.proto +@@ -40,14 +40,15 @@ message Sandbox { + // Spec is sandbox configuration (kin of OCI runtime spec), spec's data will be written to a config.json file in the + // bundle directory (similary to OCI spec). + google.protobuf.Any spec = 3; +- // Sandboxer is the name of the sandbox controller who manages the sandbox. +- string sandboxer = 4; + // Labels provides an area to include arbitrary data on containers. +- map labels = 5; ++ map labels = 4; + // CreatedAt is the time the container was first created. +- google.protobuf.Timestamp created_at = 6; ++ google.protobuf.Timestamp created_at = 5; + // UpdatedAt is the last time the container was mutated. +- google.protobuf.Timestamp updated_at = 7; ++ google.protobuf.Timestamp updated_at = 6; + // Extensions allow clients to provide optional blobs that can be handled by runtime. +- map extensions = 8; +-} ++ map extensions = 7; ++ // Sandboxer is the name of the sandbox controller who manages the sandbox. ++ string sandboxer = 10; ++ ++} +\ No newline at end of file +diff --git a/src/daemon/sandbox/controller/controller.h b/src/daemon/sandbox/controller/controller.h +index 9ad45855..60d2dee5 100644 +--- a/src/daemon/sandbox/controller/controller.h ++++ b/src/daemon/sandbox/controller/controller.h +@@ -24,6 +24,7 @@ + + #include "errors.h" + #include "api_v1.pb.h" ++#include "sandbox.pb.h" + + namespace sandbox { + +@@ -65,6 +66,7 @@ struct ControllerSandboxInfo { + uint32_t pid; + uint64_t createdAt; + std::string taskAddress; ++ std::string version; + google::protobuf::Map labels; + }; + +@@ -78,6 +80,7 @@ struct ControllerSandboxStatus { + uint32_t pid; + std::string state; + std::string taskAddress; ++ std::string version; + google::protobuf::Map info; + uint64_t createdAt; + uint64_t exitedAt; +@@ -123,11 +126,10 @@ public: + Errors &error) = 0; + virtual std::unique_ptr Start(const std::string &sandboxId, Errors &error) = 0 ; + virtual std::unique_ptr Platform(const std::string &sandboxId, Errors &error) = 0; +- virtual std::string Prepare(const std::string &sandboxId, +- const ControllerPrepareParams ¶ms, +- Errors &error) = 0; +- virtual bool Purge(const std::string &sandboxId, const std::string &containerId, +- const std::string &execId, Errors &error) = 0; ++ virtual bool Prepare(containerd::types::Sandbox &apiSandbox, ++ std::vector &fields, Errors &error) = 0; ++ virtual bool Purge(containerd::types::Sandbox &apiSandbox, ++ std::vector &fields, Errors &error) = 0; + virtual bool UpdateResources(const std::string &sandboxId, + const ControllerUpdateResourcesParams ¶ms, + Errors &error) = 0; +diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.cc b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.cc +index 11c2b014..e042ad45 100644 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.cc ++++ b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.cc +@@ -74,6 +74,7 @@ auto SandboxerClient::InitCreateRequest(containerd::services::sandbox::v1::Contr + } + } + request.set_netns_path(params.netNSPath); ++ // The arg sandbox is useless for now + return true; + } + +@@ -117,7 +118,8 @@ void SandboxerClient::StartResponseToSandboxInfo(const containerd::services::san + sandboxInfo.id = response.sandbox_id(); + sandboxInfo.pid = response.pid(); + sandboxInfo.createdAt = TimestampToNanos(response.created_at()); +- sandboxInfo.taskAddress = response.task_address(); ++ sandboxInfo.taskAddress = response.address(); ++ sandboxInfo.version = response.version(); + sandboxInfo.labels = response.labels(); + } + +@@ -144,53 +146,27 @@ auto SandboxerClient::Start(const std::string &sandboxId, ControllerSandboxInfo + return true; + } + +-auto SandboxerClient::InitPrepareRequest(containerd::services::sandbox::v1::PrepareRequest &request, +- const std::string &sandboxId, const ControllerPrepareParams ¶ms) -> bool ++void SandboxerClient::InitUpdateRequest(containerd::services::sandbox::v1::ControllerUpdateRequest &request, ++ containerd::types::Sandbox &apiSandbox, ++ std::vector &fields) + { +- if (params.spec == nullptr) { +- ERROR("Sandboxer controller prepare request failed, spec is null"); +- return false; +- } +- request.mutable_spec()->set_value(*(params.spec)); +- request.set_sandboxer(m_sandboxer); +- request.set_sandbox_id(sandboxId); +- request.set_container_id(params.containerId); +- request.set_exec_id(params.execId); +- for (const auto &entry : params.rootfs) { +- if (entry != nullptr) { +- Mount* mount = request.add_rootfs(); +- InitMountInfo(*mount, *entry); +- } +- } +- if (params.streamInfo != nullptr) { +- request.set_stdin(params.streamInfo->stdin); +- request.set_stdout(params.streamInfo->stdout); +- request.set_stderr(params.streamInfo->stderr); +- request.set_terminal(params.streamInfo->terminal); +- } else { +- request.set_stdin(""); +- request.set_stdout(""); +- request.set_stderr(""); +- request.set_terminal(false); +- } +- +- return true; ++ request.set_sandbox_id(apiSandbox.sandbox_id()); ++ request.set_sandboxer(apiSandbox.sandboxer()); ++ *(request.mutable_sandbox()) = apiSandbox; ++ *(request.mutable_fields()) = {fields.begin(), fields.end()}; + } + +-auto SandboxerClient::Prepare(const std::string &sandboxId, const ControllerPrepareParams ¶ms, std::string &bundle, +- Errors &error) -> bool ++auto SandboxerClient::Prepare(containerd::types::Sandbox &apiSandbox, ++ std::vector &fields, Errors &error) -> bool + { + grpc::ClientContext context; +- containerd::services::sandbox::v1::PrepareRequest request; +- containerd::services::sandbox::v1::PrepareResponse response; ++ containerd::services::sandbox::v1::ControllerUpdateRequest request; ++ containerd::services::sandbox::v1::ControllerUpdateResponse response; + grpc::Status status; + +- if (!InitPrepareRequest(request, sandboxId, params)) { +- error.SetError("Failed to init prepare request for sandboxer prepare request, sandbox id: " + sandboxId); +- return false; +- } ++ InitUpdateRequest(request, apiSandbox, fields); + +- status = m_stub->Prepare(&context, request, &response); ++ status = m_stub->Update(&context, request, &response); + if (!status.ok()) { + error.SetError(status.error_message()); + ERROR("Sandboxer controller prepare request failed, error_code: %d: %s", status.error_code(), +@@ -198,25 +174,20 @@ auto SandboxerClient::Prepare(const std::string &sandboxId, const ControllerPrep + return false; + } + +- bundle = response.bundle(); +- + return true; + } + +-auto SandboxerClient::Purge(const std::string &sandboxId, const std::string &containerId, +- const std::string &execId, Errors &error) -> bool ++auto SandboxerClient::Purge(containerd::types::Sandbox &apiSandbox, ++ std::vector &fields, Errors &error) -> bool + { + grpc::ClientContext context; +- containerd::services::sandbox::v1::PurgeRequest request; +- containerd::services::sandbox::v1::PurgeResponse response; ++ containerd::services::sandbox::v1::ControllerUpdateRequest request; ++ containerd::services::sandbox::v1::ControllerUpdateResponse response; + grpc::Status status; + +- request.set_sandboxer(m_sandboxer); +- request.set_sandbox_id(sandboxId); +- request.set_container_id(containerId); +- request.set_exec_id(execId); ++ InitUpdateRequest(request, apiSandbox, fields); + +- status = m_stub->Purge(&context, request, &response); ++ status = m_stub->Update(&context, request, &response); + if (!status.ok()) { + error.SetError(status.error_message()); + ERROR("Sandboxer controller purge request failed, error_code: %d: %s", status.error_code(), +@@ -227,44 +198,9 @@ auto SandboxerClient::Purge(const std::string &sandboxId, const std::string &con + return true; + } + +-auto SandboxerClient::InitUpdateResourcesRequest(containerd::services::sandbox::v1::UpdateResourcesRequest &request, +- const std::string &sandboxId, +- const ControllerUpdateResourcesParams ¶ms) -> bool +-{ +- if (params.resources == nullptr) { +- ERROR("Sandboxer controller update resources request failed, resources is null"); +- return false; +- } +- request.mutable_resources()->set_value(*(params.resources)); +- request.set_sandboxer(m_sandboxer); +- request.set_sandbox_id(sandboxId); +- request.set_container_id(params.containerId); +- request.mutable_annotations()->insert(params.annotations.begin(), params.annotations.end()); +- return true; +-} +- + auto SandboxerClient::UpdateResources(const std::string &sandboxId, const ControllerUpdateResourcesParams ¶ms, + Errors &error) -> bool + { +- grpc::ClientContext context; +- containerd::services::sandbox::v1::UpdateResourcesRequest request; +- containerd::services::sandbox::v1::UpdateResourcesResponse response; +- grpc::Status status; +- +- if (!InitUpdateResourcesRequest(request, sandboxId, params)) { +- error.SetError("Failed to init update-resources request for sandboxer update-resources request, sandbox id: " + +- sandboxId); +- return false; +- } +- +- status = m_stub->UpdateResources(&context, request, &response); +- if (!status.ok()) { +- error.SetError(status.error_message()); +- ERROR("Sandboxer controller update resources request failed, error_code: %d: %s", status.error_code(), +- status.error_message().c_str()); +- return false; +- } +- + return true; + } + +@@ -331,7 +267,8 @@ void SandboxerClient::StatusResponseToSandboxStatus(const containerd::services:: + sandboxStatus.id = response.sandbox_id(); + sandboxStatus.pid = response.pid(); + sandboxStatus.state = response.state(); +- sandboxStatus.taskAddress = response.task_address(); ++ sandboxStatus.taskAddress = response.address(); ++ sandboxStatus.version = response.version(); + sandboxStatus.info.insert(response.info().begin(), response.info().end()); + sandboxStatus.createdAt = TimestampToNanos(response.created_at()); + sandboxStatus.exitedAt = TimestampToNanos(response.exited_at()); +diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.h b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.h +index accca16b..eeb5d7f2 100644 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.h ++++ b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.h +@@ -48,11 +48,11 @@ public: + + auto Platform(const std::string &sandboxId, ControllerPlatformInfo &platformInfo, Errors &error) -> bool; + +- auto Prepare(const std::string &sandboxId, const ControllerPrepareParams ¶ms, std::string &bundle, +- Errors &error) -> bool; ++ auto Prepare(containerd::types::Sandbox &apiSandbox, ++ std::vector &fields, Errors &error) -> bool; + +- auto Purge(const std::string &sandboxId, const std::string &containerId, +- const std::string &execId, Errors &error) -> bool; ++ auto Purge(containerd::types::Sandbox &apiSandbox, ++ std::vector &fields, Errors &error) -> bool; + + auto UpdateResources(const std::string &sandboxId, const ControllerUpdateResourcesParams ¶ms, + Errors &error) -> bool; +@@ -72,11 +72,11 @@ private: + const ControllerCreateParams ¶ms) -> bool; + void StartResponseToSandboxInfo(const containerd::services::sandbox::v1::ControllerStartResponse &response, + ControllerSandboxInfo &sandboxInfo); +- auto InitPrepareRequest(containerd::services::sandbox::v1::PrepareRequest &request, +- const std::string &sandboxId, const ControllerPrepareParams ¶ms) -> bool; +- auto InitUpdateResourcesRequest(containerd::services::sandbox::v1::UpdateResourcesRequest &request, +- const std::string &sandboxId, +- const ControllerUpdateResourcesParams ¶ms) -> bool; ++ void InitUpdateRequest(containerd::services::sandbox::v1::ControllerUpdateRequest &request, ++ containerd::types::Sandbox &apiSandbox, std::vector &fields); ++ // auto InitUpdateResourcesRequest(containerd::services::sandbox::v1::UpdateResourcesRequest &request, ++ // const std::string &sandboxId, ++ // const ControllerUpdateResourcesParams ¶ms) -> bool; + void PlatformResponseToPlatformInfo(const containerd::services::sandbox::v1::ControllerPlatformResponse &response, + ControllerPlatformInfo &platformInfo); + void StatusResponseToSandboxStatus(const containerd::services::sandbox::v1::ControllerStatusResponse &response, +diff --git a/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.cc b/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.cc +index d35f1118..70cab015 100644 +--- a/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.cc ++++ b/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.cc +@@ -61,21 +61,18 @@ std::unique_ptr SandboxerController::Platform(const std: + return platformInfo; + } + +-std::string SandboxerController::Prepare(const std::string &sandboxId, +- const ControllerPrepareParams ¶ms, +- Errors &error) ++bool SandboxerController::Prepare(containerd::types::Sandbox &apiSandbox, ++ std::vector &fields, ++ Errors &error) + { +- std::string bundle; +- if (!m_client->Prepare(sandboxId, params, bundle, error)) { +- return ""; +- } +- return bundle; ++ return m_client->Prepare(apiSandbox, fields, error); + } + +-bool SandboxerController::Purge(const std::string &sandboxId, const std::string &containerId, +- const std::string &execId, Errors &error) ++bool SandboxerController::Purge(containerd::types::Sandbox &apiSandbox, ++ std::vector &fields, ++ Errors &error) + { +- return m_client->Purge(sandboxId, containerId, execId, error); ++ return m_client->Purge(apiSandbox, fields, error); + } + + bool SandboxerController::UpdateResources(const std::string &sandboxId, +diff --git a/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.h b/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.h +index ff66d3d8..8cb7fe7c 100644 +--- a/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.h ++++ b/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.h +@@ -37,11 +37,10 @@ public: + Errors &error) override; + std::unique_ptr Start(const std::string &sandboxId, Errors &error) override; + std::unique_ptr Platform(const std::string &sandboxId, Errors &error) override; +- std::string Prepare(const std::string &sandboxId, +- const ControllerPrepareParams ¶ms, +- Errors &error) override; +- bool Purge(const std::string &sandboxId, const std::string &containerId, +- const std::string &execId, Errors &error) override; ++ bool Prepare(containerd::types::Sandbox &apiSandbox, std::vector &fields, ++ Errors &error) override; ++ bool Purge(containerd::types::Sandbox &apiSandbox, std::vector &fields, ++ Errors &error) override; + bool UpdateResources(const std::string &sandboxId, + const ControllerUpdateResourcesParams ¶ms, + Errors &error) override; +diff --git a/src/daemon/sandbox/controller/shim/shim_controller.cc b/src/daemon/sandbox/controller/shim/shim_controller.cc +index ce09c076..14c99168 100644 +--- a/src/daemon/sandbox/controller/shim/shim_controller.cc ++++ b/src/daemon/sandbox/controller/shim/shim_controller.cc +@@ -340,15 +340,14 @@ std::unique_ptr ShimController::Platform(const std::stri + return nullptr; + } + +-std::string ShimController::Prepare(const std::string &sandboxId, +- const ControllerPrepareParams ¶ms, +- Errors &error) ++bool ShimController::Prepare(containerd::types::Sandbox &apiSandbox, ++ std::vector &fields, Errors &error) + { +- return std::string(""); ++ return true; + } + +-bool ShimController::Purge(const std::string &sandboxId, const std::string &containerId, +- const std::string &execId, Errors &error) ++bool ShimController::Purge(containerd::types::Sandbox &apiSandbox, ++ std::vector &fields, Errors &error) + { + return true; + } +diff --git a/src/daemon/sandbox/controller/shim/shim_controller.h b/src/daemon/sandbox/controller/shim/shim_controller.h +index 5d097bac..1985ddc0 100644 +--- a/src/daemon/sandbox/controller/shim/shim_controller.h ++++ b/src/daemon/sandbox/controller/shim/shim_controller.h +@@ -45,11 +45,10 @@ public: + Errors &error) override; + std::unique_ptr Start(const std::string &sandboxId, Errors &error) override; + std::unique_ptr Platform(const std::string &sandboxId, Errors &error) override; +- std::string Prepare(const std::string &sandboxId, +- const ControllerPrepareParams ¶ms, +- Errors &error) override; +- bool Purge(const std::string &sandboxId, const std::string &containerId, +- const std::string &execId, Errors &error) override; ++ bool Prepare(containerd::types::Sandbox &apiSandbox, std::vector &fields, ++ Errors &error) override; ++ bool Purge(containerd::types::Sandbox &apiSandbox, std::vector &fields, ++ Errors &error) override; + bool UpdateResources(const std::string &sandboxId, + const ControllerUpdateResourcesParams ¶ms, + Errors &error) override; +diff --git a/src/daemon/sandbox/sandbox.cc b/src/daemon/sandbox/sandbox.cc +index dec082bc..97b77f22 100644 +--- a/src/daemon/sandbox/sandbox.cc ++++ b/src/daemon/sandbox/sandbox.cc +@@ -494,6 +494,7 @@ auto Sandbox::Load(Errors &error) -> bool + } + + LoadNetworkSetting(); ++ LoadSandboxTasks(); + + // When the sandbox status acquisition fails or wait fails, the sandbox status is set to not ready, + // and the user decides whether to delete the sandbox. +@@ -698,6 +699,7 @@ auto Sandbox::Start(Errors &error) -> bool + m_state.pid = info->pid; + m_state.createdAt = info->createdAt; + m_taskAddress = info->taskAddress; ++ m_version = info->version; + m_state.status = SANDBOX_STATUS_RUNNING; + + if (!SaveState(error)) { +@@ -814,7 +816,7 @@ void Sandbox::Status(runtime::v1::PodSandboxStatus &status) + + auto Sandbox::GenerateSandboxStateJson(sandbox_state *state) -> std::string + { +- __isula_auto_free parser_error error; ++ __isula_auto_free parser_error error = NULL; + std::string ret; + __isula_auto_free char *state_json = NULL; + state_json = sandbox_state_generate_json(state, NULL, &(error)); +@@ -874,7 +876,7 @@ auto Sandbox::SaveNetworkSetting(Errors &error) -> bool + + auto Sandbox::GenerateSandboxMetadataJson(sandbox_metadata *metadata) -> std::string + { +- __isula_auto_free parser_error error; ++ __isula_auto_free parser_error error = NULL; + std::string ret; + __isula_auto_free char *metadata_json = NULL; + metadata_json = sandbox_metadata_generate_json(metadata, NULL, &(error)); +@@ -1096,6 +1098,11 @@ auto Sandbox::GetNetworkSettingsPath() -> std::string + return m_rootdir + std::string("/") + NETWORK_SETTINGS_JSON; + } + ++auto Sandbox::GetTasksJsonPath() -> std::string ++{ ++ return m_rootdir + std::string("/") + SANDBOX_TASKS_JSON; ++} ++ + void Sandbox::FillSandboxMetadata(sandbox_metadata* metadata, Errors &error) + { + std::string jsonStr; +@@ -1116,4 +1123,214 @@ void Sandbox::FillSandboxMetadata(sandbox_metadata* metadata, Errors &error) + + metadata->sandbox_config_json = util_strdup_s(jsonStr.c_str()); + } ++ ++auto Sandbox::AddTaskById(const char *task_id, sandbox_task *task) -> bool ++{ ++ ++ std::string taskId = std::string(task_id); ++ auto iter = m_tasks.find(taskId); ++ ++ if (iter != m_tasks.end()) { ++ ERROR("Failed to add exits sandbox task %s for sandbox: %s", ++ task_id, m_id.c_str()); ++ return false; ++ } ++ m_tasks[taskId] = std::make_shared(task); ++ return true; ++} ++ ++auto Sandbox::ReadSandboxTasksJson() -> sandbox_tasks * ++{ ++ const std::string path = GetTasksJsonPath(); ++ __isula_auto_free parser_error err = nullptr; ++ sandbox_tasks *tasksArray = nullptr; ++ ++ ReadGuard lock(m_tasksMutex); ++ tasksArray = sandbox_tasks_parse_file(path.c_str(), nullptr, &err); ++ if (tasksArray == nullptr) { ++ WARN("Failed to read %s tasks json: %s", path.c_str(), err); ++ } ++ return tasksArray; ++} ++ ++auto Sandbox::WriteSandboxTasksJson(std::string &tasks_json) -> bool ++{ ++ int nret = 0; ++ const std::string path = GetTasksJsonPath(); ++ ++ WriteGuard lock(m_tasksMutex); ++ nret = util_atomic_write_file(path.c_str(), tasks_json.c_str(), tasks_json.size(), CONFIG_FILE_MODE, false); ++ if (nret != 0) { ++ SYSERROR("Failed to write file %s", path.c_str()); ++ } ++ return nret == 0; ++} ++ ++auto Sandbox::DeleteSandboxTasksJson() -> bool ++{ ++ int get_err = 0; ++ const std::string path = GetTasksJsonPath(); ++ ++ WriteGuard lock(m_tasksMutex); ++ if (util_fileself_exists(path.c_str()) && ++ !util_force_remove_file(path.c_str(), &get_err)) { ++ errno = get_err; ++ SYSERROR("Failed to remove file %s", path.c_str()); ++ return false; ++ } ++ ++ return true; ++} ++ ++void Sandbox::AddSandboxTasksByArray(sandbox_tasks *tasksArray) ++{ ++ size_t i; ++ ++ WriteGuard lock(m_tasksMutex); ++ for (i = 0; i < tasksArray->tasks_len; i++) { ++ if (!AddTaskById(tasksArray->tasks[i]->task_id, tasksArray->tasks[i])) { ++ return; ++ } ++ tasksArray->tasks[i] = nullptr; ++ } ++ tasksArray->tasks_len = 0; ++} ++ ++void Sandbox::LoadSandboxTasks() ++{ ++ sandbox_tasks *tasksArray = nullptr; ++ ++ tasksArray = ReadSandboxTasksJson(); ++ if (tasksArray == nullptr) { ++ return; ++ } ++ ++ AddSandboxTasksByArray(tasksArray); ++ ++ free_sandbox_tasks(tasksArray); ++} ++ ++auto Sandbox::SaveSandboxTasks() -> bool ++{ ++ std::string tasks_json; ++ ++ if (m_tasks.empty()) { ++ return DeleteSandboxTasksJson(); ++ } ++ ++ tasks_json = GetAnySandboxTasks(); ++ if (tasks_json.empty()) { ++ ERROR("Failed to get sandbox tasks json for sandbox: '%s'", m_id.c_str()); ++ return false; ++ } ++ ++ return WriteSandboxTasksJson(tasks_json); ++} ++ ++auto Sandbox::AddSandboxTasks(sandbox_task *task) -> bool ++{ ++ if (task == nullptr) { ++ return true; ++ } ++ if (task->task_id == nullptr) { ++ return false; ++ } ++ ++ WriteGuard lock(m_tasksMutex); ++ ++ return AddTaskById(task->task_id, task); ++} ++ ++auto Sandbox::GetAnySandboxTasks() -> std::string ++{ ++ __isula_auto_free parser_error err = nullptr; ++ sandbox_tasks tasksArray = { 0 }; ++ size_t i = 0; ++ __isula_auto_free char *tasks_json = nullptr; ++ ++ tasksArray.tasks = (sandbox_task **)util_smart_calloc_s(sizeof(sandbox_task *), m_tasks.size()); ++ if (tasksArray.tasks == nullptr) { ++ SYSERROR("Out of memory."); ++ return std::string(""); ++ } ++ ++ ReadGuard lock(m_tasksMutex); ++ for (auto const& [_, val] : m_tasks) { ++ /* ++ * We ignore that the processes are modified ++ * when we generate tasks json string. ++ * Because no matter whether a process is deleted or added, ++ * the Update of sandbox api will be called eventually. ++ * ++ * And we ignore that the task is freed after we do GetTask(). ++ * Because the only way to free task is DeleteSandboxTasks() ++ * which needs write lock of m_tasksMutex. ++ */ ++ tasksArray.tasks[i] = val->GetTask(); ++ i++; ++ } ++ tasksArray.tasks_len = m_tasks.size(); ++ ++ tasks_json = sandbox_tasks_generate_json(&tasksArray, nullptr, &(err)); ++ if (tasks_json == nullptr || strlen(tasks_json) == 0) { ++ ERROR("Failed to get sandbox tasks json for sandbox: '%s'", m_id.c_str()); ++ free(tasksArray.tasks); ++ return std::string(""); ++ } ++ ++ free(tasksArray.tasks); ++ return std::string(tasks_json); ++} ++ ++void Sandbox::DeleteSandboxTasks(const char *containerId) ++{ ++ if (containerId == nullptr) { ++ return; ++ } ++ ++ std::string taskId = std::string(containerId); ++ ++ WriteGuard lock(m_tasksMutex); ++ auto iter = m_tasks.find(taskId); ++ if (iter == m_tasks.end()) { ++ return; ++ } ++ m_tasks.erase(iter); ++} ++ ++auto Sandbox::AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool ++{ ++ if (containerId == nullptr || processes == nullptr) { ++ ERROR("Empty args."); ++ return false; ++ } ++ ++ std::string taskId = std::string(containerId); ++ ++ ReadGuard lock(m_tasksMutex); ++ auto iter = m_tasks.find(taskId); ++ if (iter == m_tasks.end()) { ++ SYSERROR("Failed to find container %s", containerId); ++ return false; ++ } ++ ++ return iter->second->AddSandboxTasksProcess(processes); ++} ++ ++void Sandbox::DeleteSandboxTasksProcess(const char *containerId, const char *execId) ++{ ++ if (containerId == nullptr || execId == nullptr) { ++ return; ++ } ++ ++ std::string taskId = std::string(containerId); ++ ++ ReadGuard lock(m_tasksMutex); ++ auto iter = m_tasks.find(taskId); ++ if (iter == m_tasks.end()) { ++ return; ++ } ++ iter->second->DeleteSandboxTasksProcess(execId); ++} ++ + } +\ No newline at end of file +diff --git a/src/daemon/sandbox/sandbox.h b/src/daemon/sandbox/sandbox.h +index 42fbee2a..437b6113 100644 +--- a/src/daemon/sandbox/sandbox.h ++++ b/src/daemon/sandbox/sandbox.h +@@ -30,12 +30,14 @@ + #include "controller_manager.h" + #include "cstruct_wrapper.h" + #include "read_write_lock.h" ++#include "sandbox_task.h" + + namespace sandbox { + + const std::string SANDBOX_METADATA_JSON = "sandbox_metadata.json"; + const std::string SANDBOX_STATE_JSON = "sandbox_state.json"; + const std::string NETWORK_SETTINGS_JSON = "network_settings.json"; ++const std::string SANDBOX_TASKS_JSON = "sandbox_tasks.json"; + + // Keep consistent with the default values set in containerd and cri-o. + const uint32_t DEFAULT_STOP_TIMEOUT = 10; +@@ -138,6 +140,15 @@ public: + auto Remove(Errors &error) -> bool; + void Status(runtime::v1::PodSandboxStatus &status); + ++ // for sandbox api update ++ void LoadSandboxTasks(); ++ auto SaveSandboxTasks() -> bool; ++ auto AddSandboxTasks(sandbox_task *task) -> bool; ++ auto GetAnySandboxTasks() -> std::string; ++ void DeleteSandboxTasks(const char *containerId); ++ auto AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool; ++ void DeleteSandboxTasksProcess(const char *containerId, const char *execId); ++ + private: + auto SaveState(Errors &error) -> bool; + auto SaveMetadata(Errors &error) -> bool; +@@ -161,6 +172,7 @@ private: + auto GetMetadataJsonPath() -> std::string; + auto GetStatePath() -> std::string; + auto GetNetworkSettingsPath() -> std::string; ++ auto GetTasksJsonPath() -> std::string; + + void FillSandboxState(sandbox_state *state); + void FillSandboxMetadata(sandbox_metadata* metadata, Errors &error); +@@ -177,6 +189,12 @@ private: + + void updateSelinuxLabels(std::string &selinuxLabels); + ++ auto AddTaskById(const char *task_id, sandbox_task *task) -> bool; ++ auto ReadSandboxTasksJson() -> sandbox_tasks *; ++ auto WriteSandboxTasksJson(std::string &tasks_json) -> bool; ++ auto DeleteSandboxTasksJson() -> bool; ++ void AddSandboxTasksByArray(sandbox_tasks *tasksArray); ++ + private: + // Since the cri module will operate concurrently on the sandbox instance, + // use m_mutex to ensure the correctness of the sandbox instance +@@ -191,6 +209,7 @@ private: + std::string m_rootdir; + std::string m_statedir; + std::string m_taskAddress; ++ uint32_t m_version; + StatsInfo m_statsInfo; + // Store network information in the sandbox, which is convenient for the cri module to obtain + // and update the network settings of the pause container in the shim-controller. +@@ -211,6 +230,11 @@ private: + // vsock ports + std::mutex m_vsockPortsMutex; + std::set m_vsockPorts; ++ ++ // use m_tasksMutex to ensure the correctness of the tasks ++ RWMutex m_tasksMutex; ++ // for sandbox api update, containerId --> tasks ++ std::map> m_tasks; + }; + + } // namespace sandbox +diff --git a/src/daemon/sandbox/sandbox_ops.cc b/src/daemon/sandbox/sandbox_ops.cc +index 22cfea95..96e541a4 100644 +--- a/src/daemon/sandbox/sandbox_ops.cc ++++ b/src/daemon/sandbox/sandbox_ops.cc +@@ -16,11 +16,18 @@ + + #include + #include ++#include + + #include "controller_manager.h" + #include "sandbox_manager.h" ++#include "sandbox.h" + #include "namespace.h" + #include "utils.h" ++#include "utils_timestamp.h" ++ ++const std::string SANDBOX_EXTENSIONS_TASKS = "extensions.tasks"; ++const std::string SANDBOX_TASKS_KEY = "tasks"; ++const std::string SANDBOX_TASKS_TYPEURL = "github.com/containerd/containerd/Tasks"; + + static inline bool validate_sandbox_info(const container_sandbox_info *sandbox) + { +@@ -28,106 +35,166 @@ static inline bool validate_sandbox_info(const container_sandbox_info *sandbox) + sandbox->id != NULL); + } + +-static int generate_ctrl_rootfs(sandbox::ControllerPrepareParams ¶ms, ++static int generate_ctrl_rootfs(sandbox_task *task, + const container_config_v2_common_config *config) + { ++ size_t len = 1; + if (nullptr == config->base_fs) { + ERROR("Container %s has no base fs", config->id); + return -1; + } + + // TODO: rootfs's options left to be configured +- std::unique_ptr mount_info(new sandbox::ControllerMountInfo()); +- mount_info->type = MOUNT_TYPE_BIND; +- mount_info->source = config->base_fs; +- params.rootfs.push_back(std::move(mount_info)); ++ task->rootfs = (sandbox_mount **)util_smart_calloc_s(sizeof(sandbox_mount *), len); ++ if (task->rootfs == nullptr) { ++ ERROR("Out of memory."); ++ return -1; ++ } ++ task->rootfs[0] = (sandbox_mount *)util_common_calloc_s(sizeof(sandbox_mount)); ++ if (task->rootfs[0] == nullptr) { ++ ERROR("Out of memory."); ++ return -1; ++ } ++ task->rootfs_len = len; ++ task->rootfs[0]->type = util_strdup_s(MOUNT_TYPE_BIND); ++ task->rootfs[0]->source = util_strdup_s(config->base_fs); + + return 0; + } + +-static int do_sandbox_prepare(const container_config_v2_common_config *config, +- const char *exec_id, const char *oci_spec, +- const char * console_fifos[], bool tty) ++static int do_sandbox_prepare(std::shared_ptr &sandbox, containerd::types::Sandbox &apiSandbox) + { + Errors err; +- sandbox::ControllerPrepareParams params; +- std::unique_ptr stream_info(new sandbox::ControllerStreamInfo()); +- const container_sandbox_info *sandbox_info = nullptr; +- +- if (nullptr == config || nullptr == config->id) { +- ERROR("Invalid parameter: config"); +- return -1; +- } ++ std::vector fields; ++ ++ fields.push_back(SANDBOX_EXTENSIONS_TASKS); + +- sandbox_info = config->sandbox_info; +- if (false == validate_sandbox_info(sandbox_info)) { +- ERROR("Invalid parameter: sandbox"); ++ auto controller = sandbox::ControllerManager::GetInstance()->GetController(sandbox->GetSandboxer()); ++ if (nullptr == controller) { ++ ERROR("Invalid sandboxer name: %s", sandbox->GetSandboxer().c_str()); + return -1; + } + +- if (nullptr == console_fifos) { +- ERROR("Invlaid parameter: console_fifos"); ++ if (!controller->Prepare(apiSandbox, fields, err)) { ++ ERROR("Failed to prepare in container controller prepare: %s", err.GetCMessage()); + return -1; + } + +- params.containerId = config->id; +- params.execId = (nullptr == exec_id) ? "" : exec_id; +- params.spec = std::unique_ptr(new std::string(oci_spec)); +- +- if (generate_ctrl_rootfs(params, config) != 0) { +- ERROR("Invalid rootfs"); +- return -1; +- } ++ return 0; ++} + +- stream_info->stdin = (nullptr == console_fifos[0]) ? "" : console_fifos[0]; +- stream_info->stdout = (nullptr == console_fifos[1]) ? "" : console_fifos[1]; +- stream_info->stderr = (nullptr == console_fifos[2]) ? "" : console_fifos[2]; +- stream_info->terminal = tty; +- params.streamInfo = std::move(stream_info); ++static int do_sandbox_purge(std::shared_ptr &sandbox, containerd::types::Sandbox &apiSandbox) ++{ ++ Errors err; ++ std::vector fields; ++ ++ fields.push_back(SANDBOX_EXTENSIONS_TASKS); + +- auto controller = sandbox::ControllerManager::GetInstance()->GetController(sandbox_info->sandboxer); ++ auto controller = sandbox::ControllerManager::GetInstance()->GetController(sandbox->GetSandboxer()); + if (nullptr == controller) { +- ERROR("Invalid sandboxer name: %s", sandbox_info->sandboxer); ++ ERROR("Invalid sandboxer name: %s", sandbox->GetSandboxer().c_str()); + return -1; + } + +- std::string bundle = controller->Prepare(sandbox_info->id, params, err); +- if (err.NotEmpty()) { +- ERROR("Failed to prepare in container controller prepare: %s", err.GetCMessage()); ++ if (!controller->Purge(apiSandbox, fields, err)) { ++ ERROR("Failed to purge: %s", err.GetCMessage()); + return -1; + } + + return 0; + } + +-static int do_sandbox_purge(const container_config_v2_common_config *config, +- const char *exec_id) ++static oci_runtime_spec *clone_oci_runtime_spec(const oci_runtime_spec *oci_spec) + { +- Errors err; +- const container_sandbox_info *sandbox_info = nullptr; ++ __isula_auto_free char *json_str = nullptr; ++ __isula_auto_free parser_error err = nullptr; ++ oci_runtime_spec *ret = nullptr; ++ ++ json_str = oci_runtime_spec_generate_json(oci_spec, nullptr, &err); ++ if (json_str == nullptr) { ++ ERROR("Failed to generate spec json: %s", err); ++ return nullptr; ++ } ++ ret = oci_runtime_spec_parse_data(json_str, nullptr, &err); ++ if (ret == nullptr) { ++ ERROR("Failed to generate spec: %s", err); ++ } ++ return ret; ++} ++ ++static defs_process *clone_defs_process(defs_process *process_spec) ++{ ++ __isula_auto_free char *json_str = nullptr; ++ __isula_auto_free parser_error err = nullptr; ++ defs_process *ret = nullptr; ++ ++ json_str = defs_process_generate_json(process_spec, nullptr, &err); ++ if (json_str == nullptr) { ++ ERROR("Failed to generate process spec json: %s", err); ++ return nullptr; ++ } ++ ret = defs_process_parse_data(json_str, nullptr, &err); ++ if (ret == nullptr) { ++ ERROR("Failed to generate process spec: %s", err); ++ } ++ return ret; ++} + ++static std::shared_ptr get_prepare_sandbox(const container_config_v2_common_config *config) ++{ + if (nullptr == config || nullptr == config->id) { + ERROR("Invalid parameter: config"); +- return -1; ++ return nullptr; + } + +- sandbox_info = config->sandbox_info; ++ auto sandbox_info = config->sandbox_info; + if (false == validate_sandbox_info(sandbox_info)) { + ERROR("Invalid parameter: sandbox"); +- return -1; ++ return nullptr; + } + +- auto controller = sandbox::ControllerManager::GetInstance()->GetController(sandbox_info->sandboxer); +- if (nullptr == controller) { +- ERROR("Invalid sandboxer name: %s", sandbox_info->sandboxer); +- return -1; ++ auto sandbox = sandbox::SandboxManager::GetInstance()->GetSandbox(sandbox_info->id); ++ if (nullptr == sandbox) { ++ ERROR("Sandbox not found"); ++ return nullptr; + } ++ return sandbox; ++} + +- if (!controller->Purge(sandbox_info->id, config->id, +- (nullptr == exec_id) ? "" : exec_id, err)) { +- ERROR("Failed to purge: %s", err.GetCMessage()); ++static int init_prepare_api_sandbox(std::shared_ptr sandbox, const char *containerId, ++ containerd::types::Sandbox &apiSandbox) ++{ ++ google::protobuf::Map *labels = apiSandbox.mutable_labels(); ++ google::protobuf::Map *extensions = apiSandbox.mutable_extensions(); ++ google::protobuf::Any any; ++ auto created_at = new (std::nothrow) google::protobuf::Timestamp; ++ auto updated_at = new (std::nothrow) google::protobuf::Timestamp; ++ ++ apiSandbox.set_sandbox_id(sandbox->GetId()); ++ apiSandbox.mutable_runtime()->set_name(sandbox->GetRuntime()); ++ // TODO how get options ++ // apiSandbox.mutable_runtime()->set_options(sandbox->GetRuntime()); ++ // Just ignore spec ++ (*labels)[std::string("name")] = sandbox->GetName(); ++ ++ *created_at = google::protobuf::util::TimeUtil::NanosecondsToTimestamp( ++ sandbox->GetCreatedAt()); ++ apiSandbox.set_allocated_created_at(created_at); ++ *updated_at = google::protobuf::util::TimeUtil::NanosecondsToTimestamp(util_get_now_time_nanos()); ++ apiSandbox.set_allocated_updated_at(updated_at); ++ ++ auto any_type_url = any.mutable_type_url(); ++ *any_type_url = SANDBOX_TASKS_TYPEURL; ++ auto any_value = any.mutable_value(); ++ *any_value = sandbox->GetAnySandboxTasks(); ++ if ((*any_value).empty()) { ++ ERROR("Failed to get any sandbox tasks"); + return -1; + } ++ DEBUG("Get any sandbox tasks %s", (*any_value).c_str()); ++ (*extensions)[SANDBOX_TASKS_KEY] = any; ++ ++ apiSandbox.set_sandboxer(sandbox->GetSandboxer()); + + return 0; + } +@@ -136,45 +203,177 @@ int sandbox_prepare_container(const container_config_v2_common_config *config, + const oci_runtime_spec *oci_spec, + const char * console_fifos[], bool tty) + { +- __isula_auto_free char *json_oci_spec = nullptr; +- __isula_auto_free parser_error err = nullptr; ++ sandbox_task *task = nullptr; ++ containerd::types::Sandbox apiSandbox; ++ int ret = -1; + + INFO("Prepare container for sandbox"); + +- json_oci_spec = oci_runtime_spec_generate_json(oci_spec, nullptr, &err); +- if (nullptr == json_oci_spec) { +- ERROR("Failed to generate container spec json: %s", err); ++ if (nullptr == console_fifos) { ++ ERROR("Invlaid parameter: console_fifos"); ++ return -1; ++ } ++ ++ auto sandbox = get_prepare_sandbox(config); ++ if (sandbox == nullptr) { ++ ERROR("Sandbox not found"); ++ return -1; ++ } ++ ++ task = (sandbox_task *)util_common_calloc_s(sizeof(sandbox_task)); ++ if (task == nullptr) { ++ ERROR("Out of memory."); + return -1; + } +- return do_sandbox_prepare(config, nullptr, json_oci_spec, console_fifos, tty); ++ task->task_id = util_strdup_s(config->id); ++ task->spec = clone_oci_runtime_spec(oci_spec); ++ if (task->spec == nullptr) { ++ ERROR("Out of memory."); ++ goto free_out; ++ } ++ if (generate_ctrl_rootfs(task, config) != 0) { ++ ERROR("Invalid rootfs"); ++ goto free_out; ++ } ++ task->stdin = util_strdup_s((nullptr == console_fifos[0]) ? "" : console_fifos[0]); ++ task->stdout = util_strdup_s((nullptr == console_fifos[1]) ? "" : console_fifos[1]); ++ task->stderr = util_strdup_s((nullptr == console_fifos[2]) ? "" : console_fifos[2]); ++ ++ if (!sandbox->AddSandboxTasks(task)) { ++ ERROR("Failed to add sandbox %s task.", config->id); ++ goto free_out; ++ } ++ task = nullptr; ++ ret = init_prepare_api_sandbox(sandbox, config->id, apiSandbox); ++ if (ret != 0) { ++ ERROR("Failed to init %s api sandbox.", config->id); ++ goto del_out; ++ } ++ ret = do_sandbox_prepare(sandbox, apiSandbox); ++ ++del_out: ++ if (ret != 0) { ++ sandbox->DeleteSandboxTasks(config->id); ++ } ++ if (!sandbox->SaveSandboxTasks()) { ++ ERROR("Failed to Save %s sandbox tasks.", config->id); ++ ret = -1; ++ } ++free_out: ++ free_sandbox_task(task); ++ return ret; + } + + int sandbox_prepare_exec(const container_config_v2_common_config *config, + const char *exec_id, defs_process *process_spec, + const char * console_fifos[], bool tty) + { +- __isula_auto_free char *json_process = nullptr; +- __isula_auto_free parser_error err = nullptr; ++ sandbox_process *process = nullptr; ++ containerd::types::Sandbox apiSandbox; ++ int ret = -1; + + INFO("Prepare exec for container in sandbox"); + +- json_process = defs_process_generate_json(process_spec, nullptr, &err); +- if (nullptr == json_process) { +- ERROR("Failed to generate process spec json: %s", err); ++ if (nullptr == console_fifos) { ++ ERROR("Invlaid parameter: console_fifos"); + return -1; + } + +- return do_sandbox_prepare(config, exec_id, json_process, console_fifos, tty); ++ auto sandbox = get_prepare_sandbox(config); ++ if (sandbox == nullptr) { ++ ERROR("Sandbox not found"); ++ return -1; ++ } ++ ++ process = (sandbox_process *)util_common_calloc_s(sizeof(sandbox_process)); ++ if (process == nullptr) { ++ ERROR("Out of memory."); ++ return -1; ++ } ++ process->exec_id = util_strdup_s(exec_id); ++ process->spec = clone_defs_process(process_spec); ++ if (process->spec == nullptr) { ++ ERROR("Out of memory."); ++ goto free_out; ++ } ++ process->stdin = util_strdup_s((nullptr == console_fifos[0]) ? "" : console_fifos[0]); ++ process->stdout = util_strdup_s((nullptr == console_fifos[1]) ? "" : console_fifos[1]); ++ process->stderr = util_strdup_s((nullptr == console_fifos[2]) ? "" : console_fifos[2]); ++ ++ if (!sandbox->AddSandboxTasksProcess(config->id, process)) { ++ ERROR("Failed to add sandbox %s process.", config->id); ++ goto free_out; ++ } ++ process = nullptr; ++ ret = init_prepare_api_sandbox(sandbox, config->id, apiSandbox); ++ if (ret != 0) { ++ ERROR("Failed to init %s api sandbox.", config->id); ++ goto del_out; ++ } ++ ret = do_sandbox_prepare(sandbox, apiSandbox); ++ ++del_out: ++ if (ret != 0) { ++ sandbox->DeleteSandboxTasksProcess(config->id, exec_id); ++ } ++ if (!sandbox->SaveSandboxTasks()) { ++ ERROR("Failed to Save %s sandbox tasks.", config->id); ++ ret = -1; ++ } ++free_out: ++ free_sandbox_process(process); ++ return ret; + } + + int sandbox_purge_container(const container_config_v2_common_config *config) + { +- return do_sandbox_purge(config, nullptr); ++ containerd::types::Sandbox apiSandbox; ++ ++ INFO("Purge container for sandbox"); ++ ++ auto sandbox = get_prepare_sandbox(config); ++ if (sandbox == nullptr) { ++ ERROR("Sandbox not found"); ++ return -1; ++ } ++ ++ sandbox->DeleteSandboxTasks(config->id); ++ if (!sandbox->SaveSandboxTasks()) { ++ ERROR("Failed to Save %s sandbox tasks.", config->id); ++ return -1; ++ } ++ ++ if (init_prepare_api_sandbox(sandbox, config->id, apiSandbox) != 0) { ++ ERROR("Failed to init %s api sandbox.", config->id); ++ return -1; ++ } ++ return do_sandbox_purge(sandbox, apiSandbox); + } + + int sandbox_purge_exec(const container_config_v2_common_config *config, const char *exec_id) + { +- return do_sandbox_purge(config, exec_id); ++ containerd::types::Sandbox apiSandbox; ++ ++ INFO("Purge exec for container in sandbox"); ++ ++ auto sandbox = get_prepare_sandbox(config); ++ if (sandbox == nullptr) { ++ ERROR("Sandbox not found"); ++ return -1; ++ } ++ ++ sandbox->DeleteSandboxTasksProcess(config->id, exec_id); ++ if (!sandbox->SaveSandboxTasks()) { ++ ERROR("Failed to Save %s sandbox tasks.", config->id); ++ return -1; ++ } ++ ++ if (init_prepare_api_sandbox(sandbox, config->id, apiSandbox) != 0) { ++ ERROR("Failed to init %s api sandbox.", exec_id); ++ return -1; ++ } ++ ++ return do_sandbox_purge(sandbox, apiSandbox); + } + + int sandbox_on_sandbox_exit(const char *sandbox_id, int exit_code) +diff --git a/src/daemon/sandbox/sandbox_task.cc b/src/daemon/sandbox/sandbox_task.cc +new file mode 100644 +index 00000000..b1efc340 +--- /dev/null ++++ b/src/daemon/sandbox/sandbox_task.cc +@@ -0,0 +1,99 @@ ++/****************************************************************************** ++ * 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-10-22 ++ * Description: provide sandbox class definition ++ *********************************************************************************/ ++#include "sandbox_task.h" ++ ++#include ++ ++#include ++ ++#include "utils.h" ++#include "errors.h" ++ ++namespace sandbox { ++ ++SandboxTask::SandboxTask(sandbox_task *task): m_task(task) ++{ ++} ++ ++SandboxTask::~SandboxTask() ++{ ++ free_sandbox_task(m_task); ++ m_task = nullptr; ++} ++ ++auto SandboxTask::GetTask() -> sandbox_task * ++{ ++ ReadGuard lock(m_taskMutex); ++ return m_task; ++} ++ ++auto SandboxTask::AddSandboxTasksProcess(sandbox_process *processes) -> bool ++{ ++ if (processes == nullptr) { ++ ERROR("Empty args."); ++ return false; ++ } ++ ++ WriteGuard lock(m_taskMutex); ++ if (util_mem_realloc((void **)(&m_task->processes), ++ (m_task->processes_len + 1) * sizeof(sandbox_process *), ++ (void *)m_task->processes, ++ m_task->processes_len * sizeof(sandbox_process *)) != 0) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ m_task->processes[m_task->processes_len] = processes; ++ m_task->processes_len++; ++ ++ return true; ++} ++ ++auto SandboxTask::FindProcessByID(const char *execId) -> int ++{ ++ int i; ++ int processes_len = m_task->processes_len; ++ ++ if (m_task->processes == nullptr) { ++ return -1; ++ } ++ ++ for (i = 0; i < processes_len; i++) { ++ if (strcmp(m_task->processes[i]->exec_id, execId) == 0) { ++ return i; ++ } ++ } ++ return -1; ++} ++ ++void SandboxTask::DeleteSandboxTasksProcess(const char *execId) ++{ ++ if (execId == nullptr) { ++ return; ++ } ++ ++ int idx; ++ ++ WriteGuard lock(m_taskMutex); ++ idx = FindProcessByID(execId); ++ if (idx < 0) { ++ return; ++ } ++ free_sandbox_process(m_task->processes[idx]); ++ (void)memcpy((void **)&m_task->processes[idx], (void **)&m_task->processes[idx + 1], ++ (m_task->processes_len - idx - 1) * sizeof(void *)); ++ m_task->processes_len--; ++} ++ ++} +\ No newline at end of file +diff --git a/src/daemon/sandbox/sandbox_task.h b/src/daemon/sandbox/sandbox_task.h +new file mode 100644 +index 00000000..1bd0ce58 +--- /dev/null ++++ b/src/daemon/sandbox/sandbox_task.h +@@ -0,0 +1,48 @@ ++/****************************************************************************** ++ * 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-10-22 ++ * Description: provide sandbox class definition ++ *********************************************************************************/ ++ ++#ifndef DAEMON_SANDBOX_SANDBOX_TASK_H ++#define DAEMON_SANDBOX_SANDBOX_TASK_H ++ ++#include ++#include ++ ++#include ++ ++#include "api_v1.grpc.pb.h" ++#include "errors.h" ++#include "read_write_lock.h" ++ ++namespace sandbox { ++ ++class SandboxTask : public std::enable_shared_from_this { ++public: ++ SandboxTask(sandbox_task *task); ++ ~SandboxTask(); ++ ++ auto GetTask() -> sandbox_task *; ++ auto AddSandboxTasksProcess(sandbox_process *processes) -> bool; ++ void DeleteSandboxTasksProcess(const char *execId); ++ ++private: ++ auto FindProcessByID(const char *execId) -> int; ++private: ++ // Do not modify m_task concurrently. ++ RWMutex m_taskMutex; ++ sandbox_task *m_task; ++}; ++} // namespace sandbox ++ ++#endif // DAEMON_SANDBOX_SANDBOX_TASK_H +\ No newline at end of file +-- +2.34.1 + diff --git a/0152-add-omitted-macro-definition.patch b/0152-add-omitted-macro-definition.patch new file mode 100644 index 0000000000000000000000000000000000000000..630282f375a56b5ebad501ddf8c142dbac86f0cd --- /dev/null +++ b/0152-add-omitted-macro-definition.patch @@ -0,0 +1,48 @@ +From 9aadae1a71243bab41f5bf43c60f8f1b72806d54 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Fri, 22 Nov 2024 02:40:13 +1400 +Subject: [PATCH 152/156] add omitted macro definition + +Signed-off-by: zhongtao +--- + src/daemon/modules/api/runtime_api.h | 2 ++ + src/daemon/modules/service/service_container.c | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/src/daemon/modules/api/runtime_api.h b/src/daemon/modules/api/runtime_api.h +index 930710ca..1f23efe3 100644 +--- a/src/daemon/modules/api/runtime_api.h ++++ b/src/daemon/modules/api/runtime_api.h +@@ -84,7 +84,9 @@ typedef struct _rt_create_params_t { + bool tty; + bool open_stdin; + const char *task_addr; ++#ifdef ENABLE_NO_PIVOT_ROOT + bool no_pivot_root; ++#endif + } rt_create_params_t; + + typedef struct _rt_start_params_t { +diff --git a/src/daemon/modules/service/service_container.c b/src/daemon/modules/service/service_container.c +index 754c28ac..8e80e936 100644 +--- a/src/daemon/modules/service/service_container.c ++++ b/src/daemon/modules/service/service_container.c +@@ -743,6 +743,7 @@ static int do_oci_spec_update(const char *id, oci_runtime_spec *oci_spec, contai + return 0; + } + ++#ifdef ENABLE_NO_PIVOT_ROOT + static bool pack_no_pivot_root(const container_t *cont) + { + size_t i = 0; +@@ -759,6 +760,7 @@ static bool pack_no_pivot_root(const container_t *cont) + } + return ret; + } ++#endif + + static int do_start_container(container_t *cont, const char *console_fifos[], bool reset_rm, pid_ppid_info_t *pid_info) + { +-- +2.34.1 + diff --git a/0153-sandbox-sandbox-api-adapt-rust-interface.patch b/0153-sandbox-sandbox-api-adapt-rust-interface.patch new file mode 100644 index 0000000000000000000000000000000000000000..bacaa54a98ccdbcc6cb7efd9c539dc5f9b66b8da --- /dev/null +++ b/0153-sandbox-sandbox-api-adapt-rust-interface.patch @@ -0,0 +1,4272 @@ +From 32208449b2cf4de7b9c6b05b1bf58538f7f8640a Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Thu, 21 Nov 2024 11:58:36 +0800 +Subject: [PATCH 153/156] sandbox: sandbox api adapt rust interface + +Signed-off-by: liuxu +--- + cmake/options.cmake | 10 +- + cmake/protoc.cmake | 10 - + src/CMakeLists.txt | 4 + + .../sandbox/google/protobuf/any.proto | 155 ------ + .../sandbox/google/protobuf/empty.proto | 52 -- + .../sandbox/google/protobuf/timestamp.proto | 138 ------ + src/api/services/sandbox/sandbox.proto | 204 -------- + .../sandbox/sandbox/types/metrics.proto | 30 -- + .../sandbox/sandbox/types/mount.proto | 43 -- + .../sandbox/sandbox/types/platform.proto | 30 -- + .../sandbox/sandbox/types/sandbox.proto | 54 -- + src/daemon/common/cri/v1/v1_cri_helpers.cc | 3 +- + src/daemon/sandbox/CMakeLists.txt | 27 +- + .../sandbox/{controller => }/controller.h | 34 +- + src/daemon/sandbox/controller/CMakeLists.txt | 32 -- + .../sandboxer/client/CMakeLists.txt | 20 - + .../sandboxer/client/grpc_async_wait_call.cc | 142 ------ + .../sandboxer/client/grpc_async_wait_call.h | 94 ---- + .../sandboxer/client/grpc_client_utils.cc | 36 -- + .../sandboxer/client/grpc_client_utils.h | 23 - + .../sandboxer/client/grpc_sandboxer_client.cc | 337 ------------- + .../client/grpc_sandboxer_monitor.cc | 314 ------------ + .../sandboxer/client/grpc_sandboxer_monitor.h | 85 ---- + .../{controller => }/controller_manager.cc | 3 - + .../{controller => }/controller_manager.h | 0 + src/daemon/sandbox/sandbox.cc | 215 -------- + src/daemon/sandbox/sandbox.h | 26 +- + src/daemon/sandbox/sandbox_manager.cc | 44 +- + src/daemon/sandbox/sandbox_ops.cc | 250 +++++++--- + src/daemon/sandbox/sandbox_task.cc | 7 +- + src/daemon/sandbox/sandboxer/CMakeLists.txt | 15 + + .../controller}/CMakeLists.txt | 0 + .../controller/client/CMakeLists.txt | 12 + + .../client/grpc_sandboxer_client.cc | 463 ++++++++++++++++++ + .../client/grpc_sandboxer_client.h | 46 +- + .../controller}/sandboxer_controller.cc | 27 +- + .../controller}/sandboxer_controller.h | 9 +- + .../sandbox/sandboxer/sandboxer_sandbox.cc | 254 ++++++++++ + .../sandbox/sandboxer/sandboxer_sandbox.h | 63 +++ + src/daemon/sandbox/shim/CMakeLists.txt | 15 + + .../shim => shim/controller}/CMakeLists.txt | 0 + .../controller}/shim_controller.cc | 19 +- + .../controller}/shim_controller.h | 12 +- + src/daemon/sandbox/shim/shim_sandbox.cc | 65 +++ + src/daemon/sandbox/shim/shim_sandbox.h | 49 ++ + 45 files changed, 1225 insertions(+), 2246 deletions(-) + delete mode 100644 src/api/services/sandbox/google/protobuf/any.proto + delete mode 100644 src/api/services/sandbox/google/protobuf/empty.proto + delete mode 100644 src/api/services/sandbox/google/protobuf/timestamp.proto + delete mode 100644 src/api/services/sandbox/sandbox.proto + delete mode 100644 src/api/services/sandbox/sandbox/types/metrics.proto + delete mode 100644 src/api/services/sandbox/sandbox/types/mount.proto + delete mode 100644 src/api/services/sandbox/sandbox/types/platform.proto + delete mode 100644 src/api/services/sandbox/sandbox/types/sandbox.proto + rename src/daemon/sandbox/{controller => }/controller.h (79%) + delete mode 100644 src/daemon/sandbox/controller/CMakeLists.txt + delete mode 100755 src/daemon/sandbox/controller/sandboxer/client/CMakeLists.txt + delete mode 100644 src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.cc + delete mode 100644 src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.h + delete mode 100644 src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.cc + delete mode 100644 src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.h + delete mode 100644 src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.cc + delete mode 100644 src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.cc + delete mode 100644 src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.h + rename src/daemon/sandbox/{controller => }/controller_manager.cc (98%) + rename src/daemon/sandbox/{controller => }/controller_manager.h (100%) + create mode 100755 src/daemon/sandbox/sandboxer/CMakeLists.txt + rename src/daemon/sandbox/{controller/sandboxer => sandboxer/controller}/CMakeLists.txt (100%) + create mode 100755 src/daemon/sandbox/sandboxer/controller/client/CMakeLists.txt + create mode 100644 src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.cc + rename src/daemon/sandbox/{controller/sandboxer => sandboxer/controller}/client/grpc_sandboxer_client.h (54%) + rename src/daemon/sandbox/{controller/sandboxer => sandboxer/controller}/sandboxer_controller.cc (78%) + rename src/daemon/sandbox/{controller/sandboxer => sandboxer/controller}/sandboxer_controller.h (82%) + create mode 100644 src/daemon/sandbox/sandboxer/sandboxer_sandbox.cc + create mode 100644 src/daemon/sandbox/sandboxer/sandboxer_sandbox.h + create mode 100755 src/daemon/sandbox/shim/CMakeLists.txt + rename src/daemon/sandbox/{controller/shim => shim/controller}/CMakeLists.txt (100%) + rename src/daemon/sandbox/{controller/shim => shim/controller}/shim_controller.cc (97%) + rename src/daemon/sandbox/{controller/shim => shim/controller}/shim_controller.h (89%) + create mode 100644 src/daemon/sandbox/shim/shim_sandbox.cc + create mode 100644 src/daemon/sandbox/shim/shim_sandbox.h + +diff --git a/cmake/options.cmake b/cmake/options.cmake +index 41177fe0..cee83ef2 100644 +--- a/cmake/options.cmake ++++ b/cmake/options.cmake +@@ -53,9 +53,13 @@ endif() + + option(ENABLE_SANDBOXER "Enable sandbox API" OFF) + if (ENABLE_SANDBOXER STREQUAL "ON") +- add_definitions(-DENABLE_SANDBOXER) +- set(ENABLE_SANDBOXER 1) +- message("${Green}-- Enable sandbox API${ColourReset}") ++ if (ENABLE_CRI_API_V1) ++ add_definitions(-DENABLE_SANDBOXER) ++ set(ENABLE_SANDBOXER 1) ++ message("${Green}-- Enable sandbox API${ColourReset}") ++ else() ++ message("${Yellow}-- Can not enable sandboxer, sandboxer need enable CRI API V1 first ${ColourReset}") ++ endif() + endif() + + option(ENABLE_OOM_MONITOR "Enable oom monitor" ON) +diff --git a/cmake/protoc.cmake b/cmake/protoc.cmake +index 6343fe3e..de337f25 100644 +--- a/cmake/protoc.cmake ++++ b/cmake/protoc.cmake +@@ -66,13 +66,3 @@ if (GRPC_CONNECTOR) + PROTOC_GRPC_GEN(network ${NETWORK_PROTOS_OUT_PATH} ${PROTOS_PATH}/network/network.proto) + endif() + endif() +- +-if (ENABLE_CRI_API_V1 AND ENABLE_SANDBOXER) +- execute_process(COMMAND mkdir -p ${SANDBOX_PROTOS_OUT_PATH}) +- PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox/types/sandbox.proto) +- PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox/types/mount.proto) +- PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox/types/platform.proto) +- PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox/types/metrics.proto) +- PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox.proto) +- PROTOC_GRPC_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox.proto) +-endif() +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 70a8ac91..6aab3f69 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -200,6 +200,10 @@ else() + set_target_properties(isulad PROPERTIES LINKER_LANGUAGE "C") + endif() + ++if (ENABLE_SANDBOXER) ++ target_link_libraries(isulad isula_sandbox) ++endif() ++ + target_link_libraries(isulad libisulad_tools libhttpclient -ldl) + if (ANDROID OR MUSL) + target_link_libraries(isulad ${LIBSSL_LIBRARY} ${LIBYAJL_LIBRARY}) +diff --git a/src/api/services/sandbox/google/protobuf/any.proto b/src/api/services/sandbox/google/protobuf/any.proto +deleted file mode 100644 +index c9be8541..00000000 +--- a/src/api/services/sandbox/google/protobuf/any.proto ++++ /dev/null +@@ -1,155 +0,0 @@ +-// Protocol Buffers - Google's data interchange format +-// Copyright 2008 Google Inc. All rights reserved. +-// https://developers.google.com/protocol-buffers/ +-// +-// Redistribution and use in source and binary forms, with or without +-// modification, are permitted provided that the following conditions are +-// met: +-// +-// * Redistributions of source code must retain the above copyright +-// notice, this list of conditions and the following disclaimer. +-// * Redistributions in binary form must reproduce the above +-// copyright notice, this list of conditions and the following disclaimer +-// in the documentation and/or other materials provided with the +-// distribution. +-// * Neither the name of Google Inc. nor the names of its +-// contributors may be used to endorse or promote products derived from +-// this software without specific prior written permission. +-// +-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- +-syntax = "proto3"; +- +-package google.protobuf; +- +-option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +-option go_package = "github.com/golang/protobuf/ptypes/any"; +-option java_package = "com.google.protobuf"; +-option java_outer_classname = "AnyProto"; +-option java_multiple_files = true; +-option objc_class_prefix = "GPB"; +- +-// `Any` contains an arbitrary serialized protocol buffer message along with a +-// URL that describes the type of the serialized message. +-// +-// Protobuf library provides support to pack/unpack Any values in the form +-// of utility functions or additional generated methods of the Any type. +-// +-// Example 1: Pack and unpack a message in C++. +-// +-// Foo foo = ...; +-// Any any; +-// any.PackFrom(foo); +-// ... +-// if (any.UnpackTo(&foo)) { +-// ... +-// } +-// +-// Example 2: Pack and unpack a message in Java. +-// +-// Foo foo = ...; +-// Any any = Any.pack(foo); +-// ... +-// if (any.is(Foo.class)) { +-// foo = any.unpack(Foo.class); +-// } +-// +-// Example 3: Pack and unpack a message in Python. +-// +-// foo = Foo(...) +-// any = Any() +-// any.Pack(foo) +-// ... +-// if any.Is(Foo.DESCRIPTOR): +-// any.Unpack(foo) +-// ... +-// +-// Example 4: Pack and unpack a message in Go +-// +-// foo := &pb.Foo{...} +-// any, err := ptypes.MarshalAny(foo) +-// ... +-// foo := &pb.Foo{} +-// if err := ptypes.UnmarshalAny(any, foo); err != nil { +-// ... +-// } +-// +-// The pack methods provided by protobuf library will by default use +-// 'type.googleapis.com/full.type.name' as the type URL and the unpack +-// methods only use the fully qualified type name after the last '/' +-// in the type URL, for example "foo.bar.com/x/y.z" will yield type +-// name "y.z". +-// +-// +-// JSON +-// ==== +-// The JSON representation of an `Any` value uses the regular +-// representation of the deserialized, embedded message, with an +-// additional field `@type` which contains the type URL. Example: +-// +-// package google.profile; +-// message Person { +-// string first_name = 1; +-// string last_name = 2; +-// } +-// +-// { +-// "@type": "type.googleapis.com/google.profile.Person", +-// "firstName": , +-// "lastName": +-// } +-// +-// If the embedded message type is well-known and has a custom JSON +-// representation, that representation will be embedded adding a field +-// `value` which holds the custom JSON in addition to the `@type` +-// field. Example (for message [google.protobuf.Duration][]): +-// +-// { +-// "@type": "type.googleapis.com/google.protobuf.Duration", +-// "value": "1.212s" +-// } +-// +-message Any { +- // A URL/resource name that uniquely identifies the type of the serialized +- // protocol buffer message. This string must contain at least +- // one "/" character. The last segment of the URL's path must represent +- // the fully qualified name of the type (as in +- // `path/google.protobuf.Duration`). The name should be in a canonical form +- // (e.g., leading "." is not accepted). +- // +- // In practice, teams usually precompile into the binary all types that they +- // expect it to use in the context of Any. However, for URLs which use the +- // scheme `http`, `https`, or no scheme, one can optionally set up a type +- // server that maps type URLs to message definitions as follows: +- // +- // * If no scheme is provided, `https` is assumed. +- // * An HTTP GET on the URL must yield a [google.protobuf.Type][] +- // value in binary format, or produce an error. +- // * Applications are allowed to cache lookup results based on the +- // URL, or have them precompiled into a binary to avoid any +- // lookup. Therefore, binary compatibility needs to be preserved +- // on changes to types. (Use versioned type names to manage +- // breaking changes.) +- // +- // Note: this functionality is not currently available in the official +- // protobuf release, and it is not used for type URLs beginning with +- // type.googleapis.com. +- // +- // Schemes other than `http`, `https` (or the empty scheme) might be +- // used with implementation specific semantics. +- // +- string type_url = 1; +- +- // Must be a valid serialized protocol buffer of the above specified type. +- bytes value = 2; +-} +diff --git a/src/api/services/sandbox/google/protobuf/empty.proto b/src/api/services/sandbox/google/protobuf/empty.proto +deleted file mode 100644 +index 03cacd23..00000000 +--- a/src/api/services/sandbox/google/protobuf/empty.proto ++++ /dev/null +@@ -1,52 +0,0 @@ +-// Protocol Buffers - Google's data interchange format +-// Copyright 2008 Google Inc. All rights reserved. +-// https://developers.google.com/protocol-buffers/ +-// +-// Redistribution and use in source and binary forms, with or without +-// modification, are permitted provided that the following conditions are +-// met: +-// +-// * Redistributions of source code must retain the above copyright +-// notice, this list of conditions and the following disclaimer. +-// * Redistributions in binary form must reproduce the above +-// copyright notice, this list of conditions and the following disclaimer +-// in the documentation and/or other materials provided with the +-// distribution. +-// * Neither the name of Google Inc. nor the names of its +-// contributors may be used to endorse or promote products derived from +-// this software without specific prior written permission. +-// +-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- +-syntax = "proto3"; +- +-package google.protobuf; +- +-option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +-option go_package = "github.com/golang/protobuf/ptypes/empty"; +-option java_package = "com.google.protobuf"; +-option java_outer_classname = "EmptyProto"; +-option java_multiple_files = true; +-option objc_class_prefix = "GPB"; +-option cc_enable_arenas = true; +- +-// A generic empty message that you can re-use to avoid defining duplicated +-// empty messages in your APIs. A typical example is to use it as the request +-// or the response type of an API method. For instance: +-// +-// service Foo { +-// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); +-// } +-// +-// The JSON representation for `Empty` is empty JSON object `{}`. +-message Empty {} +diff --git a/src/api/services/sandbox/google/protobuf/timestamp.proto b/src/api/services/sandbox/google/protobuf/timestamp.proto +deleted file mode 100644 +index cd357864..00000000 +--- a/src/api/services/sandbox/google/protobuf/timestamp.proto ++++ /dev/null +@@ -1,138 +0,0 @@ +-// Protocol Buffers - Google's data interchange format +-// Copyright 2008 Google Inc. All rights reserved. +-// https://developers.google.com/protocol-buffers/ +-// +-// Redistribution and use in source and binary forms, with or without +-// modification, are permitted provided that the following conditions are +-// met: +-// +-// * Redistributions of source code must retain the above copyright +-// notice, this list of conditions and the following disclaimer. +-// * Redistributions in binary form must reproduce the above +-// copyright notice, this list of conditions and the following disclaimer +-// in the documentation and/or other materials provided with the +-// distribution. +-// * Neither the name of Google Inc. nor the names of its +-// contributors may be used to endorse or promote products derived from +-// this software without specific prior written permission. +-// +-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +- +-syntax = "proto3"; +- +-package google.protobuf; +- +-option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +-option cc_enable_arenas = true; +-option go_package = "github.com/golang/protobuf/ptypes/timestamp"; +-option java_package = "com.google.protobuf"; +-option java_outer_classname = "TimestampProto"; +-option java_multiple_files = true; +-option objc_class_prefix = "GPB"; +- +-// A Timestamp represents a point in time independent of any time zone or local +-// calendar, encoded as a count of seconds and fractions of seconds at +-// nanosecond resolution. The count is relative to an epoch at UTC midnight on +-// January 1, 1970, in the proleptic Gregorian calendar which extends the +-// Gregorian calendar backwards to year one. +-// +-// All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap +-// second table is needed for interpretation, using a [24-hour linear +-// smear](https://developers.google.com/time/smear). +-// +-// The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By +-// restricting to that range, we ensure that we can convert to and from [RFC +-// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. +-// +-// # Examples +-// +-// Example 1: Compute Timestamp from POSIX `time()`. +-// +-// Timestamp timestamp; +-// timestamp.set_seconds(time(NULL)); +-// timestamp.set_nanos(0); +-// +-// Example 2: Compute Timestamp from POSIX `gettimeofday()`. +-// +-// struct timeval tv; +-// gettimeofday(&tv, NULL); +-// +-// Timestamp timestamp; +-// timestamp.set_seconds(tv.tv_sec); +-// timestamp.set_nanos(tv.tv_usec * 1000); +-// +-// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. +-// +-// FILETIME ft; +-// GetSystemTimeAsFileTime(&ft); +-// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; +-// +-// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z +-// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. +-// Timestamp timestamp; +-// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); +-// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); +-// +-// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. +-// +-// long millis = System.currentTimeMillis(); +-// +-// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) +-// .setNanos((int) ((millis % 1000) * 1000000)).build(); +-// +-// +-// Example 5: Compute Timestamp from current time in Python. +-// +-// timestamp = Timestamp() +-// timestamp.GetCurrentTime() +-// +-// # JSON Mapping +-// +-// In JSON format, the Timestamp type is encoded as a string in the +-// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the +-// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" +-// where {year} is always expressed using four digits while {month}, {day}, +-// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional +-// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), +-// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone +-// is required. A proto3 JSON serializer should always use UTC (as indicated by +-// "Z") when printing the Timestamp type and a proto3 JSON parser should be +-// able to accept both UTC and other timezones (as indicated by an offset). +-// +-// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past +-// 01:30 UTC on January 15, 2017. +-// +-// In JavaScript, one can convert a Date object to this format using the +-// standard +-// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) +-// method. In Python, a standard `datetime.datetime` object can be converted +-// to this format using +-// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with +-// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use +-// the Joda Time's [`ISODateTimeFormat.dateTime()`]( +-// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D +-// ) to obtain a formatter capable of generating timestamps in this format. +-// +-// +-message Timestamp { +- // Represents seconds of UTC time since Unix epoch +- // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to +- // 9999-12-31T23:59:59Z inclusive. +- int64 seconds = 1; +- +- // Non-negative fractions of a second at nanosecond resolution. Negative +- // second values with fractions must still have non-negative nanos values +- // that count forward in time. Must be from 0 to 999,999,999 +- // inclusive. +- int32 nanos = 2; +-} +diff --git a/src/api/services/sandbox/sandbox.proto b/src/api/services/sandbox/sandbox.proto +deleted file mode 100644 +index dcc78444..00000000 +--- a/src/api/services/sandbox/sandbox.proto ++++ /dev/null +@@ -1,204 +0,0 @@ +-/* +- Copyright The containerd Authors. +- +- Licensed under the Apache License, Version 2.0 (the "License"); +- you may not use this file except in compliance with the License. +- You may obtain a copy of the License at +- +- http://www.apache.org/licenses/LICENSE-2.0 +- +- Unless required by applicable law or agreed to in writing, software +- distributed under the License is distributed on an "AS IS" BASIS, +- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +- See the License for the specific language governing permissions and +- limitations under the License. +-*/ +- +-syntax = "proto3"; +- +-// Sandbox is a v2 runtime extension that allows more complex execution environments for containers. +-// This adds a notion of groups of containers that share same lifecycle and/or resources. +-// A few good fits for sandbox can be: +-// - A "pause" container in k8s, that acts as a parent process for child containers to hold network namespace. +-// - (micro)VMs that launch a VM process and executes containers inside guest OS. +-// containerd in this case remains implementation agnostic and delegates sandbox handling to runtimes. +-// See proposal and discussion here: https://github.com/containerd/containerd/issues/4131 +-package containerd.services.sandbox.v1; +- +-import "google/protobuf/any.proto"; +-import "google/protobuf/timestamp.proto"; +- +-import "sandbox/types/sandbox.proto"; +-import "sandbox/types/mount.proto"; +-import "sandbox/types/platform.proto"; +-import "sandbox/types/metrics.proto"; +- +-option go_package = "github.com/containerd/containerd/api/services/sandbox/v1;sandbox"; +- +-// Store provides a metadata storage interface for sandboxes. Similarly to `Containers`, +-// sandbox object includes info required to start a new instance, but no runtime state. +-// When running a new sandbox instance, store objects are used as base type to create from. +-service Store { +- rpc Create(StoreCreateRequest) returns (StoreCreateResponse); +- rpc Update(StoreUpdateRequest) returns (StoreUpdateResponse); +- rpc Delete(StoreDeleteRequest) returns (StoreDeleteResponse); +- rpc List(StoreListRequest) returns (StoreListResponse); +- rpc Get(StoreGetRequest) returns (StoreGetResponse); +-} +- +-message StoreCreateRequest { +- containerd.types.Sandbox sandbox = 1; +-} +- +-message StoreCreateResponse { +- containerd.types.Sandbox sandbox = 1; +-} +- +-message StoreUpdateRequest { +- containerd.types.Sandbox sandbox = 1; +- repeated string fields = 2; +-} +- +-message StoreUpdateResponse { +- containerd.types.Sandbox sandbox = 1; +-} +- +-message StoreDeleteRequest { +- string sandbox_id = 1; +-} +- +-message StoreDeleteResponse {} +- +-message StoreListRequest { +- repeated string filters = 1; +-} +- +-message StoreListResponse { +- repeated containerd.types.Sandbox list = 1; +-} +- +-message StoreGetRequest { +- string sandbox_id = 1; +-} +- +-message StoreGetResponse { +- containerd.types.Sandbox sandbox = 1; +-} +- +-// Controller is an interface to manage runtime sandbox instances. +-service Controller { +- rpc Create(ControllerCreateRequest) returns (ControllerCreateResponse); +- rpc Start(ControllerStartRequest) returns (ControllerStartResponse); +- rpc Platform(ControllerPlatformRequest) returns (ControllerPlatformResponse); +- rpc Stop(ControllerStopRequest) returns (ControllerStopResponse); +- rpc Wait(ControllerWaitRequest) returns (ControllerWaitResponse); +- rpc Status(ControllerStatusRequest) returns (ControllerStatusResponse); +- rpc Shutdown(ControllerShutdownRequest) returns (ControllerShutdownResponse); +- rpc Metrics(ControllerMetricsRequest) returns (ControllerMetricsResponse); +- rpc Update(ControllerUpdateRequest) returns (ControllerUpdateResponse); +-} +- +-message ControllerCreateRequest { +- string sandbox_id = 1; +- repeated containerd.types.Mount rootfs = 2; +- google.protobuf.Any options = 3; +- string netns_path = 4; +- map annotations = 5; +- containerd.types.Sandbox sandbox = 6; +- string sandboxer = 10; +-} +- +-message ControllerCreateResponse { +- string sandbox_id = 1; +-} +- +-message ControllerStartRequest { +- string sandbox_id = 1; +- string sandboxer = 10; +-} +- +-message ControllerStartResponse { +- string sandbox_id = 1; +- uint32 pid = 2; +- google.protobuf.Timestamp created_at = 3; +- map labels = 4; +- // Address of the sandbox for containerd to connect, +- // for calling Task or other APIs serving in the sandbox. +- // it is in the form of ttrpc+unix://path/to/uds or grpc+vsock://:. +- string address = 5; +- uint32 version = 6; +-} +- +-message ControllerPlatformRequest { +- string sandbox_id = 1; +- string sandboxer = 10; +-} +- +-message ControllerPlatformResponse { +- containerd.types.Platform platform = 1; +-} +- +-message ControllerStopRequest { +- string sandbox_id = 1; +- uint32 timeout_secs = 2; +- string sandboxer = 10; +-} +- +-message ControllerStopResponse {} +- +-message ControllerWaitRequest { +- string sandbox_id = 1; +- string sandboxer = 10; +-} +- +-message ControllerWaitResponse { +- uint32 exit_status = 1; +- google.protobuf.Timestamp exited_at = 2; +-} +- +-message ControllerStatusRequest { +- string sandbox_id = 1; +- bool verbose = 2; +- string sandboxer = 10; +-} +- +-message ControllerStatusResponse { +- string sandbox_id = 1; +- uint32 pid = 2; +- string state = 3; +- map info = 4; +- google.protobuf.Timestamp created_at = 5; +- google.protobuf.Timestamp exited_at = 6; +- google.protobuf.Any extra = 7; +- // Address of the sandbox for containerd to connect, +- // for calling Task or other APIs serving in the sandbox. +- // it is in the form of ttrpc+unix://path/to/uds or grpc+vsock://:. +- string address = 8; +- uint32 version = 9; +-} +- +-message ControllerShutdownRequest { +- string sandbox_id = 1; +- string sandboxer = 10; +-} +- +-message ControllerShutdownResponse {} +- +-message ControllerMetricsRequest { +- string sandbox_id = 1; +- string sandboxer = 10; +-} +- +-message ControllerMetricsResponse { +- types.Metric metrics = 1; +-} +- +-message ControllerUpdateRequest { +- string sandbox_id = 1; +- string sandboxer = 2; +- containerd.types.Sandbox sandbox = 3; +- repeated string fields = 4; +-} +- +-message ControllerUpdateResponse { +-} +\ No newline at end of file +diff --git a/src/api/services/sandbox/sandbox/types/metrics.proto b/src/api/services/sandbox/sandbox/types/metrics.proto +deleted file mode 100644 +index 61185939..00000000 +--- a/src/api/services/sandbox/sandbox/types/metrics.proto ++++ /dev/null +@@ -1,30 +0,0 @@ +-/* +- Copyright The containerd Authors. +- +- Licensed under the Apache License, Version 2.0 (the "License"); +- you may not use this file except in compliance with the License. +- You may obtain a copy of the License at +- +- http://www.apache.org/licenses/LICENSE-2.0 +- +- Unless required by applicable law or agreed to in writing, software +- distributed under the License is distributed on an "AS IS" BASIS, +- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +- See the License for the specific language governing permissions and +- limitations under the License. +-*/ +- +-syntax = "proto3"; +- +-package containerd.types; +- +-import "google/protobuf/any.proto"; +-import "google/protobuf/timestamp.proto"; +- +-option go_package = "github.com/containerd/containerd/api/types;types"; +- +-message Metric { +- google.protobuf.Timestamp timestamp = 1; +- string id = 2; +- google.protobuf.Any data = 3; +-} +\ No newline at end of file +diff --git a/src/api/services/sandbox/sandbox/types/mount.proto b/src/api/services/sandbox/sandbox/types/mount.proto +deleted file mode 100644 +index 54e0a0cd..00000000 +--- a/src/api/services/sandbox/sandbox/types/mount.proto ++++ /dev/null +@@ -1,43 +0,0 @@ +-/* +- Copyright The containerd Authors. +- +- Licensed under the Apache License, Version 2.0 (the "License"); +- you may not use this file except in compliance with the License. +- You may obtain a copy of the License at +- +- http://www.apache.org/licenses/LICENSE-2.0 +- +- Unless required by applicable law or agreed to in writing, software +- distributed under the License is distributed on an "AS IS" BASIS, +- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +- See the License for the specific language governing permissions and +- limitations under the License. +-*/ +- +-syntax = "proto3"; +- +-package containerd.types; +- +-option go_package = "github.com/containerd/containerd/api/types;types"; +- +-// Mount describes mounts for a container. +-// +-// This type is the lingua franca of ContainerD. All services provide mounts +-// to be used with the container at creation time. +-// +-// The Mount type follows the structure of the mount syscall, including a type, +-// source, target and options. +-message Mount { +- // Type defines the nature of the mount. +- string type = 1; +- +- // Source specifies the name of the mount. Depending on mount type, this +- // may be a volume name or a host path, or even ignored. +- string source = 2; +- +- // Target path in container +- string target = 3; +- +- // Options specifies zero or more fstab style mount options. +- repeated string options = 4; +-} +diff --git a/src/api/services/sandbox/sandbox/types/platform.proto b/src/api/services/sandbox/sandbox/types/platform.proto +deleted file mode 100644 +index 102e6e2b..00000000 +--- a/src/api/services/sandbox/sandbox/types/platform.proto ++++ /dev/null +@@ -1,30 +0,0 @@ +-/* +- Copyright The containerd Authors. +- +- Licensed under the Apache License, Version 2.0 (the "License"); +- you may not use this file except in compliance with the License. +- You may obtain a copy of the License at +- +- http://www.apache.org/licenses/LICENSE-2.0 +- +- Unless required by applicable law or agreed to in writing, software +- distributed under the License is distributed on an "AS IS" BASIS, +- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +- See the License for the specific language governing permissions and +- limitations under the License. +-*/ +- +-syntax = "proto3"; +- +-package containerd.types; +- +-option go_package = "github.com/containerd/containerd/api/types;types"; +- +-// Platform follows the structure of the OCI platform specification, from +-// descriptors. +-message Platform { +- string os = 1; +- string architecture = 2; +- string variant = 3; +- string os_version = 4; +-} +\ No newline at end of file +diff --git a/src/api/services/sandbox/sandbox/types/sandbox.proto b/src/api/services/sandbox/sandbox/types/sandbox.proto +deleted file mode 100644 +index 6fe08d40..00000000 +--- a/src/api/services/sandbox/sandbox/types/sandbox.proto ++++ /dev/null +@@ -1,54 +0,0 @@ +-/* +- Copyright The containerd Authors. +- +- Licensed under the Apache License, Version 2.0 (the "License"); +- you may not use this file except in compliance with the License. +- You may obtain a copy of the License at +- +- http://www.apache.org/licenses/LICENSE-2.0 +- +- Unless required by applicable law or agreed to in writing, software +- distributed under the License is distributed on an "AS IS" BASIS, +- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +- See the License for the specific language governing permissions and +- limitations under the License. +-*/ +- +-syntax = "proto3"; +- +-package containerd.types; +- +-import "google/protobuf/any.proto"; +-import "google/protobuf/timestamp.proto"; +- +-option go_package = "github.com/containerd/containerd/api/types;types"; +- +-// Sandbox represents a sandbox metadata object that keeps all info required by controller to +-// work with a particular instance. +-message Sandbox { +- // SandboxID is a unique instance identifier within namespace +- string sandbox_id = 1; +- message Runtime { +- // Name is the name of the runtime. +- string name = 1; +- // Options specify additional runtime initialization options for the shim (this data will be available in StartShim). +- // Typically this data expected to be runtime shim implementation specific. +- google.protobuf.Any options = 2; +- } +- // Runtime specifies which runtime to use for executing this container. +- Runtime runtime = 2; +- // Spec is sandbox configuration (kin of OCI runtime spec), spec's data will be written to a config.json file in the +- // bundle directory (similary to OCI spec). +- google.protobuf.Any spec = 3; +- // Labels provides an area to include arbitrary data on containers. +- map labels = 4; +- // CreatedAt is the time the container was first created. +- google.protobuf.Timestamp created_at = 5; +- // UpdatedAt is the last time the container was mutated. +- google.protobuf.Timestamp updated_at = 6; +- // Extensions allow clients to provide optional blobs that can be handled by runtime. +- map extensions = 7; +- // Sandboxer is the name of the sandbox controller who manages the sandbox. +- string sandboxer = 10; +- +-} +\ No newline at end of file +diff --git a/src/daemon/common/cri/v1/v1_cri_helpers.cc b/src/daemon/common/cri/v1/v1_cri_helpers.cc +index 31b6b137..dfe14ade 100644 +--- a/src/daemon/common/cri/v1/v1_cri_helpers.cc ++++ b/src/daemon/common/cri/v1/v1_cri_helpers.cc +@@ -397,7 +397,7 @@ std::string CRISandboxerConvert(const std::string &runtime) + std::string sandboxer; + defs_map_string_object_sandboxer *criSandboxerList = nullptr; + +- if (runtime.empty() || runtime == DEFAULT_SANDBOXER_NAME) { ++ if (runtime.empty()) { + return DEFAULT_SANDBOXER_NAME; + } + +@@ -412,6 +412,7 @@ std::string CRISandboxerConvert(const std::string &runtime) + goto out; + } + ++ sandboxer = DEFAULT_SANDBOXER_NAME; + criSandboxerList = args->json_confs->cri_sandboxers; + for (size_t i = 0; i < criSandboxerList->len; i++) { + if (criSandboxerList->keys[i] == nullptr || criSandboxerList->values[i] == nullptr || +diff --git a/src/daemon/sandbox/CMakeLists.txt b/src/daemon/sandbox/CMakeLists.txt +index 7679ea68..2c31f243 100644 +--- a/src/daemon/sandbox/CMakeLists.txt ++++ b/src/daemon/sandbox/CMakeLists.txt +@@ -1,15 +1,32 @@ + # get current directory sources files + + aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} sandbox_top_srcs) +-add_subdirectory(controller) + +-set(SANDBOX_SRCS ++set(local_sandbox_top_srcs + ${sandbox_top_srcs} +- ${SANDBOX_CONTROLLER_SRCS} ++ ) ++set(local_sandbox_top_incs ++ ${CMAKE_CURRENT_SOURCE_DIR} ++ ) ++ ++if (ENABLE_CRI_API_V1 AND ENABLE_SANDBOXER) ++ add_subdirectory(sandboxer) ++ list (APPEND local_sandbox_top_srcs ++ ${SANDBOXER_SANDBOX_SRCS} ++ ) ++ list (APPEND local_sandbox_top_incs ++ ${SANDBOXER_SANDBOX_INCS} ++ ) ++endif() ++ ++add_subdirectory(shim) ++set(SANDBOX_SRCS ++ ${local_sandbox_top_srcs} ++ ${SHIM_SANDBOX_SRCS} + PARENT_SCOPE + ) + set(SANDBOX_INCS +- ${CMAKE_CURRENT_SOURCE_DIR} +- ${SANDBOX_CONTROLLER_INCS} ++ ${local_sandbox_top_incs} ++ ${SHIM_SANDBOX_INCS} + PARENT_SCOPE + ) +\ No newline at end of file +diff --git a/src/daemon/sandbox/controller/controller.h b/src/daemon/sandbox/controller.h +similarity index 79% +rename from src/daemon/sandbox/controller/controller.h +rename to src/daemon/sandbox/controller.h +index 60d2dee5..0975015a 100644 +--- a/src/daemon/sandbox/controller/controller.h ++++ b/src/daemon/sandbox/controller.h +@@ -22,15 +22,19 @@ + #include + #include + ++#include ++ + #include "errors.h" + #include "api_v1.pb.h" +-#include "sandbox.pb.h" ++#include "utils_array.h" + + namespace sandbox { + + #define SANDBOX_READY_STATE_STR "SANDBOX_READY" + #define SANDBOX_NOTREADY_STATE_STR "SANDBOX_NOTREADY" + ++const std::string SHIM_CONTROLLER_NAME = "shim"; ++ + struct ControllerMountInfo { + std::string source; + std::string destination; +@@ -66,7 +70,7 @@ struct ControllerSandboxInfo { + uint32_t pid; + uint64_t createdAt; + std::string taskAddress; +- std::string version; ++ uint32_t version; + google::protobuf::Map labels; + }; + +@@ -80,7 +84,7 @@ struct ControllerSandboxStatus { + uint32_t pid; + std::string state; + std::string taskAddress; +- std::string version; ++ uint32_t version; + google::protobuf::Map info; + uint64_t createdAt; + uint64_t exitedAt; +@@ -95,20 +99,6 @@ struct ControllerStreamInfo { + bool terminal; + }; + +-struct ControllerPrepareParams { +- std::string containerId; +- std::string execId; +- std::unique_ptr spec; +- std::vector> rootfs; +- std::unique_ptr streamInfo; +-}; +- +-struct ControllerUpdateResourcesParams { +- std::string containerId; +- std::unique_ptr resources; +- google::protobuf::Map &annotations; +-}; +- + class SandboxStatusCallback { + public: + virtual void OnSandboxReady() = 0; +@@ -120,19 +110,13 @@ class Controller { + public: + virtual ~Controller() {}; + virtual bool Init(Errors &error) = 0; +- virtual void Destroy() = 0; + virtual bool Create(const std::string &sandboxId, + const ControllerCreateParams ¶ms, + Errors &error) = 0; + virtual std::unique_ptr Start(const std::string &sandboxId, Errors &error) = 0 ; + virtual std::unique_ptr Platform(const std::string &sandboxId, Errors &error) = 0; +- virtual bool Prepare(containerd::types::Sandbox &apiSandbox, +- std::vector &fields, Errors &error) = 0; +- virtual bool Purge(containerd::types::Sandbox &apiSandbox, +- std::vector &fields, Errors &error) = 0; +- virtual bool UpdateResources(const std::string &sandboxId, +- const ControllerUpdateResourcesParams ¶ms, +- Errors &error) = 0; ++ virtual bool Update(sandbox_sandbox *apiSandbox, ++ string_array *fields, Errors &error) = 0; + virtual bool Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) = 0; + virtual bool Wait(std::shared_ptr cb, const std::string &sandboxId, Errors &error) = 0; + virtual std::unique_ptr Status(const std::string &sandboxId, bool verbose, Errors &error) = 0; +diff --git a/src/daemon/sandbox/controller/CMakeLists.txt b/src/daemon/sandbox/controller/CMakeLists.txt +deleted file mode 100644 +index 8764c05b..00000000 +--- a/src/daemon/sandbox/controller/CMakeLists.txt ++++ /dev/null +@@ -1,32 +0,0 @@ +-# get current directory sources files +- +-aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} sandbox_controller_top_srcs) +- +-set(local_sandbox_controller_top_srcs +- ${sandbox_controller_top_srcs} +- ) +-set(local_sandbox_controller_top_incs +- ${CMAKE_CURRENT_SOURCE_DIR} +- ) +- +-if (ENABLE_CRI_API_V1 AND ENABLE_SANDBOXER) +- add_subdirectory(sandboxer) +- list (APPEND local_sandbox_controller_top_srcs +- ${CONTROLLER_SANDBOXER_SRCS} +- ) +- list (APPEND local_sandbox_controller_top_incs +- ${CONTROLLER_SANDBOXER_INCS} +- ) +-endif() +- +-add_subdirectory(shim) +-set(SANDBOX_CONTROLLER_SRCS +- ${local_sandbox_controller_top_srcs} +- ${CONTROLLER_SHIM_SRCS} +- PARENT_SCOPE +- ) +-set(SANDBOX_CONTROLLER_INCS +- ${local_sandbox_controller_top_incs} +- ${CONTROLLER_SHIM_INCS} +- PARENT_SCOPE +- ) +\ No newline at end of file +diff --git a/src/daemon/sandbox/controller/sandboxer/client/CMakeLists.txt b/src/daemon/sandbox/controller/sandboxer/client/CMakeLists.txt +deleted file mode 100755 +index 958ebaa5..00000000 +--- a/src/daemon/sandbox/controller/sandboxer/client/CMakeLists.txt ++++ /dev/null +@@ -1,20 +0,0 @@ +-# get current directory sources files +-aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} sandbox_controller_sandboxer_client_srcs) +-aux_source_directory(${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox grpc_sandbox_api_srcs) +-aux_source_directory(${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/google/protobuf grpc_sandbox_google_protobuf_api_srcs) +-aux_source_directory(${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox/types sandbox_type_srcs) +- +- +-set(CONTROLLER_SANDBOXER_CLIENT_SRCS +- ${sandbox_controller_sandboxer_client_srcs} +- ${grpc_sandbox_api_srcs} +- ${grpc_sandbox_google_protobuf_api_srcs} +- ${sandbox_type_srcs} +- PARENT_SCOPE +- ) +- +-set(CONTROLLER_SANDBOXER_CLIENT_INCS +- ${CMAKE_CURRENT_SOURCE_DIR} +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox +- PARENT_SCOPE +- ) +diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.cc b/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.cc +deleted file mode 100644 +index c6f97da1..00000000 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.cc ++++ /dev/null +@@ -1,142 +0,0 @@ +-/****************************************************************************** +- * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: xuxuepeng +- * Create: 2023-07-28 +- * Description: gRPC Async wait call object +- ******************************************************************************/ +- +-#include "grpc_async_wait_call.h" +- +-#include +-#include +- +-#include "grpc_client_utils.h" +- +-namespace sandbox { +- +-// Max retry counter. In monitor thread, we will check deferred calls every 200ms +-// so if a call has retry counter for 1500, it means the call will be retried after 300 seconds +-const int64_t MAX_RETRY_COUNTER = 1500; // 1500 * 200ms = 300s +- +-SandboxerAsyncWaitCall::SandboxerAsyncWaitCall(std::shared_ptr cb, +- const std::string &sandboxId, const std::string &sandboxer) +- : m_cb(cb), m_sandboxId(sandboxId), m_sandboxer(sandboxer) +-{ +- m_status = grpc::Status::OK; +- m_retryTimes = 0; +- m_retryCounter = 0; +- m_remove = false; +-} +- +-auto SandboxerAsyncWaitCall::Call(containerd::services::sandbox::v1::Controller::StubInterface &stub, +- grpc::CompletionQueue &cq) -> bool +-{ +- containerd::services::sandbox::v1::ControllerWaitRequest request; +- m_context = std::unique_ptr(new grpc::ClientContext()); +- request.set_sandboxer(m_sandboxer); +- request.set_sandbox_id(m_sandboxId); +- m_responseReader = stub.PrepareAsyncWait(m_context.get(), request, &cq); +- if (m_responseReader == nullptr) { +- // Most likely the completion queue is shutdown +- ERROR("Failed to prepare async wait request for sandboxer wait request, sandbox id: %s", m_sandboxId.c_str()); +- SandboxExitCallback(false, ControllerExitInfo()); +- return false; +- } +- m_responseReader->StartCall(); +- m_responseReader->Finish(&m_response, &m_status, (void *)this); +- return true; +-} +- +-auto SandboxerAsyncWaitCall::SandboxExitCallback(bool statusOK, const ControllerExitInfo &exitInfo) -> void +-{ +- // If statusOK is false, it means something unexpected happened during async wait, +- // the exitInfo is not valid, but we assume that the sandbox has exited. +- if (!statusOK) { +- ControllerExitInfo info; +- auto currentTime = std::chrono::high_resolution_clock::now(); +- auto duration = currentTime.time_since_epoch(); +- info.exitedAt = std::chrono::duration_cast(duration).count(); +- info.exitStatus = -1; +- m_cb->OnSandboxExit(info); +- return; +- } +- m_cb->OnSandboxExit(exitInfo); +-} +- +-auto SandboxerAsyncWaitCall::SandboxPendingCallback() -> void +-{ +- m_cb->OnSandboxPending(); +-} +- +-auto SandboxerAsyncWaitCall::SandboxReadyCallback() -> void +-{ +- m_cb->OnSandboxReady(); +-} +- +-auto SandboxerAsyncWaitCall::Timeout() -> bool +-{ +- m_retryCounter--; +- return m_retryCounter == 0; +-} +- +-auto SandboxerAsyncWaitCall::GetSandboxId() -> const std::string & +-{ +- return m_sandboxId; +-} +- +-SandboxerAsyncWaitStatus SandboxerAsyncWaitCall::HandleResponse() +-{ +- ControllerExitInfo exitInfo; +- SandboxerAsyncWaitStatus waitStatus = SANDBOXER_ASYNC_WAIT_STATUS_ERROR; +- +- switch (m_status.error_code()) { +- case grpc::StatusCode::UNAVAILABLE: +- // If the status is unavailable, connection failed, we should retry +- WARN("Sandboxer controller wait rpc server unavailable, error_code: %d: %s", m_status.error_code(), +- m_status.error_message().c_str()); +- waitStatus = SANDBOXER_ASYNC_WAIT_STATUS_RETRY; +- m_retryTimes++; +- // If retried times is more than 10, we should retry every 300 seconds +- if (m_retryTimes > 10) { +- m_retryCounter = MAX_RETRY_COUNTER; +- } else { +- // Retry interval is 2 ^ retry times +- m_retryCounter = 1 << m_retryTimes; +- } +- m_cb->OnSandboxPending(); +- break; +- case grpc::StatusCode::OK: +- exitInfo.exitedAt = TimestampToNanos(m_response.exited_at()); +- exitInfo.exitStatus = m_response.exit_status(); +- DEBUG("Sandboxer controller wait request success, sandbox id: %s, exit status: %d, exited at: %lu", +- m_sandboxId.c_str(), exitInfo.exitStatus, exitInfo.exitedAt); +- SandboxExitCallback(true, exitInfo); +- waitStatus = SANDBOXER_ASYNC_WAIT_STATUS_OK; +- break; +- case grpc::StatusCode::NOT_FOUND: +- // If the sandbox is not found, it has been deleted, we should return not found +- WARN("The sandbox wait doesn't exist, sandbox id: %s, error_code: %d: %s", +- m_sandboxId.c_str(), m_status.error_code(), m_status.error_message().c_str()); +- waitStatus = SANDBOXER_ASYNC_WAIT_STATUS_NOT_FOUND; +- SandboxExitCallback(false, exitInfo); +- break; +- default: +- // TODO: More error code should be handled +- ERROR("Sandboxer controller wait request failed, error_code: %d: %s", m_status.error_code(), +- m_status.error_message().c_str()); +- SandboxExitCallback(false, exitInfo); +- break; +- } +- +- return waitStatus; +-} +- +-}; // namespace sandbox +\ No newline at end of file +diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.h b/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.h +deleted file mode 100644 +index 6e5a6756..00000000 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.h ++++ /dev/null +@@ -1,94 +0,0 @@ +-/****************************************************************************** +- * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: xuxuepeng +- * Create: 2023-07-28 +- * Description: gRPC Async wait call object +- ******************************************************************************/ +- +-#ifndef DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_ASYNC_WAIT_CALL_H +-#define DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_ASYNC_WAIT_CALL_H +- +-#include +- +-#include "sandbox.pb.h" +-#include "sandbox.grpc.pb.h" +- +-#include "controller.h" +- +-namespace sandbox { +- +-enum SandboxerAsyncWaitStatus { +- SANDBOXER_ASYNC_WAIT_STATUS_OK = 0, +- SANDBOXER_ASYNC_WAIT_STATUS_RETRY, +- SANDBOXER_ASYNC_WAIT_STATUS_NOT_FOUND, +- SANDBOXER_ASYNC_WAIT_STATUS_ERROR, +-}; +- +-/** +- * SandboxerAsyncWaitCall is used to call the async wait method. +- * It will be passed to completion queue to wait for the response. +- * When the response is received, HandleResponse will be called. +- */ +-class SandboxerAsyncWaitCall { +-public: +- SandboxerAsyncWaitCall(std::shared_ptr cb, +- const std::string &sandboxId, const std::string &sandboxer); +- virtual ~SandboxerAsyncWaitCall() = default; +- auto Call(containerd::services::sandbox::v1::Controller::StubInterface &stub, grpc::CompletionQueue &cq) -> bool; +- auto HandleResponse() -> SandboxerAsyncWaitStatus; +- auto Timeout() -> bool; +- void SandboxExitCallback(bool statusOK, const ControllerExitInfo &exitInfo); +- void SandboxPendingCallback(); +- void SandboxReadyCallback(); +- auto GetSandboxId() -> const std::string &; +- auto MarkRemove() -> void +- { +- m_remove = true; +- } +- auto ToRemove() -> bool +- { +- return m_remove; +- } +- auto ResetRetryTimes() -> void +- { +- m_retryTimes = 0; +- } +- +-protected: +- std::shared_ptr m_stub; +- std::shared_ptr m_cb; +- std::string m_sandboxId; +- std::string m_sandboxer; +- std::unique_ptr> +- m_responseReader; +- std::unique_ptr m_context; +- containerd::services::sandbox::v1::ControllerWaitResponse m_response; +- grpc::Status m_status; +- uint32_t m_retryTimes; +- uint64_t m_retryCounter; +- // The Call object will be deleted when it is unable to be enqueued to completion queue. +- // However, since gRPC call happens in async function in Future object, there is potential race condition +- // when deleting the call object: +- // 1. Monitor thread cleanup future object first, which holding the reference to call object, and +- // then AysncCompletionRpcThread received response for the call later, and delete the call object. +- // It is OK in this case, since future release the call ownership, and the call object deleted later. +- // 2. AsyncCompletionRpcThread received response for the call first, and delete the call object, and +- // then Monitor thread cleanup future object later, which could cause use-after-free, since monitor +- // thread will use the call to call the callback when cleaning the future object. +- // So we need to mark the call object as removed, cleanup them together in Monitor thread after checking +- // the future objects. +- bool m_remove; +-}; +- +- +-}; // namespace sandbox +- +-#endif // DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_ASYNC_WAIT_CALL_H +\ No newline at end of file +diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.cc b/src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.cc +deleted file mode 100644 +index 2cc5a11e..00000000 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.cc ++++ /dev/null +@@ -1,36 +0,0 @@ +-/****************************************************************************** +- * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: xuxuepeng +- * Create: 2023-07-28 +- * Description: grpc client utils functions +- ******************************************************************************/ +- +-#include "grpc_client_utils.h" +- +-const uint64_t SECOND_TO_NANOS = 1000000000; +-const int64_t MAX_SECONDS_FOR_TIMESTAMP = 253402300799; // 9999-12-31T23:59:59Z +-const int32_t MAX_NANOS_FOR_TIMESTAMP = 999999999; +- +-auto TimestampToNanos(const google::protobuf::Timestamp ×tamp) -> uint64_t +-{ +- int64_t seconds = 0; +- int32_t nanos = 0; +- +- seconds = timestamp.seconds(); +- seconds = seconds < 0 ? 0 : seconds; +- seconds = seconds > MAX_SECONDS_FOR_TIMESTAMP ? MAX_SECONDS_FOR_TIMESTAMP : seconds; +- +- nanos = timestamp.nanos(); +- nanos = nanos < 0 ? 0 : nanos; +- nanos = nanos > MAX_NANOS_FOR_TIMESTAMP ? MAX_NANOS_FOR_TIMESTAMP : nanos; +- +- return seconds * SECOND_TO_NANOS + nanos; +-} +diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.h b/src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.h +deleted file mode 100644 +index 105d33fc..00000000 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.h ++++ /dev/null +@@ -1,23 +0,0 @@ +-/****************************************************************************** +- * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: xuxuepeng +- * Create: 2023-07-28 +- * Description: grpc client utils functions +- ******************************************************************************/ +- +-#ifndef DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_CLIENT_UTILS_H +-#define DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_CLIENT_UTILS_H +- +-#include +- +-uint64_t TimestampToNanos(const google::protobuf::Timestamp ×tamp); +- +-#endif // DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_CLIENT_UTILS_H +\ No newline at end of file +diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.cc b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.cc +deleted file mode 100644 +index e042ad45..00000000 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.cc ++++ /dev/null +@@ -1,337 +0,0 @@ +-/****************************************************************************** +- * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: xuxuepeng +- * Create: 2023-07-10 +- * Description: Sandboxer grpc client +- ******************************************************************************/ +- +-#include "grpc_sandboxer_client.h" +- +-#include +-#include +-#include +-#include +-#include +- +-#include "sandbox/types/platform.pb.h" +-#include "sandbox.pb.h" +-#include "sandbox.grpc.pb.h" +-#include "utils.h" +-#include "isula_libutils/log.h" +- +-#include "grpc_client_utils.h" +- +-namespace sandbox { +- +-SandboxerClient::SandboxerClient(const std::string &sandboxer, const std::string &address): +- m_sandboxer(sandboxer), m_address(address) +-{ +- std::string unixPrefix(UNIX_SOCKET_PREFIX); +- +- // Only support unix domain socket +- if (m_address.compare(0, unixPrefix.length(), unixPrefix) != 0) { +- m_address = unixPrefix + m_address; +- } +- m_channel = grpc::CreateChannel(m_address, grpc::InsecureChannelCredentials()); +- m_stub = containerd::services::sandbox::v1::Controller::NewStub(m_channel); +- // Monitor shares the same channel with client and has its own stub +- m_monitor = std::unique_ptr(new SandboxerClientMonitor(m_channel, m_sandboxer)); +-} +- +-void SandboxerClient::InitMountInfo(Mount &mount, const ControllerMountInfo &mountInfo) +-{ +- mount.set_type(mountInfo.type); +- mount.set_source(mountInfo.source); +- mount.set_target(mountInfo.destination); +- for (const auto &option : mountInfo.options) { +- mount.add_options(option); +- } +-} +- +-auto SandboxerClient::InitCreateRequest(containerd::services::sandbox::v1::ControllerCreateRequest &request, +- const std::string &sandboxId, +- const ControllerCreateParams ¶ms) -> bool +-{ +- if (params.config == nullptr) { +- ERROR("Sandboxer controller create request failed, config is null"); +- return false; +- } +- request.mutable_options()->PackFrom(*params.config); +- request.set_sandboxer(m_sandboxer); +- request.set_sandbox_id(sandboxId); +- for (const auto &entry : params.mounts) { +- if (entry != nullptr) { +- Mount* mount = request.add_rootfs(); +- InitMountInfo(*mount, *entry); +- } +- } +- request.set_netns_path(params.netNSPath); +- // The arg sandbox is useless for now +- return true; +-} +- +-void SandboxerClient::Init(Errors &error) +-{ +- m_monitor->Start(); +-} +- +-void SandboxerClient::Destroy() +-{ +- m_monitor->Stop(); +-} +- +-auto SandboxerClient::Create(const std::string &sandboxId, const ControllerCreateParams ¶ms, Errors &error) -> bool +-{ +- grpc::ClientContext context; +- containerd::services::sandbox::v1::ControllerCreateRequest request; +- containerd::services::sandbox::v1::ControllerCreateResponse response; +- grpc::Status status; +- +- if (!InitCreateRequest(request, sandboxId, params)) { +- error.SetError("Failed to init create request for sandboxer create request, sandbox id: " + sandboxId); +- return false; +- } +- +- status = m_stub->Create(&context, request, &response); +- if (!status.ok()) { +- error.SetError(status.error_message()); +- ERROR("Sandboxer controller create request failed, error_code: %d: %s", status.error_code(), +- status.error_message().c_str()); +- return false; +- } +- +- return true; +-} +- +-void SandboxerClient::StartResponseToSandboxInfo(const containerd::services::sandbox::v1::ControllerStartResponse +- &response, +- ControllerSandboxInfo &sandboxInfo) +-{ +- sandboxInfo.id = response.sandbox_id(); +- sandboxInfo.pid = response.pid(); +- sandboxInfo.createdAt = TimestampToNanos(response.created_at()); +- sandboxInfo.taskAddress = response.address(); +- sandboxInfo.version = response.version(); +- sandboxInfo.labels = response.labels(); +-} +- +-auto SandboxerClient::Start(const std::string &sandboxId, ControllerSandboxInfo &sandboxInfo, Errors &error) -> bool +-{ +- grpc::ClientContext context; +- containerd::services::sandbox::v1::ControllerStartRequest request; +- containerd::services::sandbox::v1::ControllerStartResponse response; +- grpc::Status status; +- +- request.set_sandboxer(m_sandboxer); +- request.set_sandbox_id(sandboxId); +- +- status = m_stub->Start(&context, request, &response); +- if (!status.ok()) { +- error.SetError(status.error_message()); +- ERROR("Sandboxer controller start request failed, error_code: %d: %s", status.error_code(), +- status.error_message().c_str()); +- return false; +- } +- +- StartResponseToSandboxInfo(response, sandboxInfo); +- +- return true; +-} +- +-void SandboxerClient::InitUpdateRequest(containerd::services::sandbox::v1::ControllerUpdateRequest &request, +- containerd::types::Sandbox &apiSandbox, +- std::vector &fields) +-{ +- request.set_sandbox_id(apiSandbox.sandbox_id()); +- request.set_sandboxer(apiSandbox.sandboxer()); +- *(request.mutable_sandbox()) = apiSandbox; +- *(request.mutable_fields()) = {fields.begin(), fields.end()}; +-} +- +-auto SandboxerClient::Prepare(containerd::types::Sandbox &apiSandbox, +- std::vector &fields, Errors &error) -> bool +-{ +- grpc::ClientContext context; +- containerd::services::sandbox::v1::ControllerUpdateRequest request; +- containerd::services::sandbox::v1::ControllerUpdateResponse response; +- grpc::Status status; +- +- InitUpdateRequest(request, apiSandbox, fields); +- +- status = m_stub->Update(&context, request, &response); +- if (!status.ok()) { +- error.SetError(status.error_message()); +- ERROR("Sandboxer controller prepare request failed, error_code: %d: %s", status.error_code(), +- status.error_message().c_str()); +- return false; +- } +- +- return true; +-} +- +-auto SandboxerClient::Purge(containerd::types::Sandbox &apiSandbox, +- std::vector &fields, Errors &error) -> bool +-{ +- grpc::ClientContext context; +- containerd::services::sandbox::v1::ControllerUpdateRequest request; +- containerd::services::sandbox::v1::ControllerUpdateResponse response; +- grpc::Status status; +- +- InitUpdateRequest(request, apiSandbox, fields); +- +- status = m_stub->Update(&context, request, &response); +- if (!status.ok()) { +- error.SetError(status.error_message()); +- ERROR("Sandboxer controller purge request failed, error_code: %d: %s", status.error_code(), +- status.error_message().c_str()); +- return false; +- } +- +- return true; +-} +- +-auto SandboxerClient::UpdateResources(const std::string &sandboxId, const ControllerUpdateResourcesParams ¶ms, +- Errors &error) -> bool +-{ +- return true; +-} +- +-void SandboxerClient::PlatformResponseToPlatformInfo(const containerd::services::sandbox::v1::ControllerPlatformResponse +- &response, +- ControllerPlatformInfo &platformInfo) +-{ +- auto &platform = response.platform(); +- platformInfo.os = platform.os(); +- platformInfo.arch = platform.architecture(); +- platformInfo.variant = platform.variant(); +-} +- +-auto SandboxerClient::Platform(const std::string &sandboxId, ControllerPlatformInfo &platformInfo, +- Errors &error) -> bool +-{ +- grpc::ClientContext context; +- containerd::services::sandbox::v1::ControllerPlatformRequest request; +- containerd::services::sandbox::v1::ControllerPlatformResponse response; +- grpc::Status status; +- +- request.set_sandboxer(m_sandboxer); +- request.set_sandbox_id(sandboxId); +- +- status = m_stub->Platform(&context, request, &response); +- if (!status.ok()) { +- error.SetError(status.error_message()); +- ERROR("Sandboxer controller platform request failed, error_code: %d: %s", status.error_code(), +- status.error_message().c_str()); +- return false; +- } +- +- PlatformResponseToPlatformInfo(response, platformInfo); +- +- return true; +-} +- +-auto SandboxerClient::Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) -> bool +-{ +- grpc::ClientContext context; +- containerd::services::sandbox::v1::ControllerStopRequest request; +- containerd::services::sandbox::v1::ControllerStopResponse response; +- grpc::Status status; +- +- request.set_sandboxer(m_sandboxer); +- request.set_sandbox_id(sandboxId); +- request.set_timeout_secs(timeoutSecs); +- +- status = m_stub->Stop(&context, request, &response); +- if (!status.ok()) { +- error.SetError(status.error_message()); +- ERROR("Sandboxer controller stop request failed, error_code: %d: %s", status.error_code(), +- status.error_message().c_str()); +- return false; +- } +- +- return true; +-} +- +-void SandboxerClient::StatusResponseToSandboxStatus(const containerd::services::sandbox::v1::ControllerStatusResponse +- &response, +- ControllerSandboxStatus &sandboxStatus) +-{ +- sandboxStatus.id = response.sandbox_id(); +- sandboxStatus.pid = response.pid(); +- sandboxStatus.state = response.state(); +- sandboxStatus.taskAddress = response.address(); +- sandboxStatus.version = response.version(); +- sandboxStatus.info.insert(response.info().begin(), response.info().end()); +- sandboxStatus.createdAt = TimestampToNanos(response.created_at()); +- sandboxStatus.exitedAt = TimestampToNanos(response.exited_at()); +- sandboxStatus.extra = response.extra().value(); +-} +- +-auto SandboxerClient::Status(const std::string &sandboxId, bool verbose, ControllerSandboxStatus &sandboxStatus, +- Errors &error) -> bool +-{ +- grpc::ClientContext context; +- containerd::services::sandbox::v1::ControllerStatusRequest request; +- containerd::services::sandbox::v1::ControllerStatusResponse response; +- grpc::Status status; +- +- request.set_sandboxer(m_sandboxer); +- request.set_sandbox_id(sandboxId); +- request.set_verbose(verbose); +- +- status = m_stub->Status(&context, request, &response); +- if (!status.ok()) { +- error.SetError(status.error_message()); +- ERROR("Sandboxer controller status request failed, error_code: %d: %s", status.error_code(), +- status.error_message().c_str()); +- return false; +- } +- +- StatusResponseToSandboxStatus(response, sandboxStatus); +- +- return true; +-} +- +-auto SandboxerClient::Shutdown(const std::string &sandboxId, Errors &error) -> bool +-{ +- grpc::ClientContext context; +- containerd::services::sandbox::v1::ControllerShutdownRequest request; +- containerd::services::sandbox::v1::ControllerShutdownResponse response; +- grpc::Status status; +- +- request.set_sandboxer(m_sandboxer); +- request.set_sandbox_id(sandboxId); +- +- status = m_stub->Shutdown(&context, request, &response); +- if (!status.ok()) { +- error.SetError(status.error_message()); +- ERROR("Sandboxer controller shutdown request failed, error_code: %d: %s", status.error_code(), +- status.error_message().c_str()); +- return false; +- } +- +- return true; +-} +- +-auto SandboxerClient::Wait(std::shared_ptr cb, const std::string &sandboxId, +- Errors &error) -> bool +-{ +- if (m_monitor == nullptr) { +- error.SetError("Cannot wait for sandbox, sandboxer client monitor is not initialized, " +- "sandboxer: " + m_sandboxer); +- return false; +- } +- SandboxerAsyncWaitCall *call = new SandboxerAsyncWaitCall(cb, sandboxId, m_sandboxer); +- // Transfer ownership of call to monitor +- return m_monitor->Monitor(call); +-} +- +-} // namespace +diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.cc b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.cc +deleted file mode 100644 +index 485a0b23..00000000 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.cc ++++ /dev/null +@@ -1,314 +0,0 @@ +-/****************************************************************************** +- * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: xuxuepeng +- * Create: 2023-07-28 +- * Description: Sandboxer grpc client monitor +- ******************************************************************************/ +- +-#include "grpc_sandboxer_monitor.h" +- +-#include +- +-#include "isula_libutils/log.h" +- +-namespace sandbox { +- +-const int64_t DEFERRED_QUEUE_CHECK_INTERVAL = 200; // milliseconds +- +-SandboxerClientMonitor::SandboxerClientMonitor(std::shared_ptr channel, const std::string &sandboxer): +- m_channel(channel), m_sandboxer(sandboxer), m_teardown(false) +-{ +- m_stub = containerd::services::sandbox::v1::Controller::NewStub(m_channel); +-} +- +-// Monitor will gain the ownership of the call object, and is responsible +-// for deleting it +-auto SandboxerClientMonitor::Monitor(SandboxerAsyncWaitCall *call) -> bool +-{ +- if (call == nullptr) { +- ERROR("Async wait call is null, failed to monitor."); +- return false; +- } +- +- if (m_teardown) { +- ERROR("Monitor is already shutdown, failed to monitor sandbox, id: %s", +- call->GetSandboxId().c_str()); +- delete call; +- return false; +- } +- +- // Try to monitor the call, if failed, we should delete it right way +- if (!call->Call(*m_stub, m_cq)) { +- // The failure is most likely due to the fact that the completion queue is shutdown +- delete call; +- return false; +- } +- // The call will be enqueued into completion queue, and the callback +- // will be invoked when the response is ready +- std::unique_lock lock(m_callsMutex); +- m_calls.push_back(call); +- INFO("Start to monitor sandboxer wait call, sandbox id: %s", +- call->GetSandboxId().c_str()); +- return true; +-} +- +-void SandboxerClientMonitor::Start() +-{ +- m_cqThread = std::thread(&SandboxerClientMonitor::AsyncCompleteRpcThread, this); +- m_deferredThread = std::thread(&SandboxerClientMonitor::MonitorThread, this); +-} +- +-void SandboxerClientMonitor::Stop() +-{ +- // At the time of shutdown, the calls objects are in three states: +- // 1. In the completion queue, waiting for the response +- // 2. In the deferred queue, waiting for the dispatch +- // 3. In the future queue, are about to get into completion queue +- // We should cleanup all those objects +- m_cq.Shutdown(); +- m_teardown = true; +- // In case the deferred queue is empty, we should notify the condition variable +- m_deferredCallsCond.notify_one(); +- INFO("Stopping sandboxer wait call monitor, sandboxer: %s", m_sandboxer.c_str()); +- // Wait until all the threads exit +- m_cqThread.join(); +- m_deferredThread.join(); +-} +- +-auto SandboxerClientMonitor::IsAlive() -> bool +-{ +- // GetState will retry the channel connection if channel is not active when the parameter is true. +- // Monitor will keep retrying with wait call, so we dont have to let channel reconnect here, use false instead. +- return m_channel->GetState(false) == GRPC_CHANNEL_READY; +-} +- +-// When the call needs to be retried, we should put it into the deferred queue +-void SandboxerClientMonitor::AddDeferredCall(SandboxerAsyncWaitCall *call) +-{ +- std::unique_lock lock(m_deferredCallsMutex); +- m_deferredCalls.push_back(call); +- m_deferredCallsCond.notify_one(); +-} +- +-// When the deferred queue and future queue are empty, we should wait for the condition signal +-void SandboxerClientMonitor::WaitForDeferredCall() +-{ +- std::unique_lock lock(m_deferredCallsMutex); +- // Check m_futures queue here as well just in case m_futures queue is +- if (m_deferredCalls.empty() && m_futures.empty() && !m_teardown) { +- m_deferredCallsCond.wait(lock); +- } +-} +- +-// Retry the call after a random sleep time +-// There are two return values for the future: +-// 1. bool: Indicate the call has been successfully retried and enqueued into completion queue +-// 2. SandboxerAsyncWaitCall *: The call handled by the future +-void SandboxerClientMonitor::InvokeDeferredCall(SandboxerAsyncWaitCall *call) +-{ +- m_futures.push_back(std::async([this, call]() { +- // Random sleep for 50 ~ 200 milliseconds to avoid thundering herd +- std::random_device rd; +- std::mt19937 gen(rd()); +- std::uniform_int_distribution<> dis(DEFERRED_QUEUE_CHECK_INTERVAL / 4, DEFERRED_QUEUE_CHECK_INTERVAL); +- int sleepTime = dis(gen); +- std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime)); +- +- if (this->m_teardown) { +- // If the monitor is already shutdown, the call will be cleaned up +- // by the cleanup function +- return std::pair(false, nullptr); +- } +- if (!call->Call(*m_stub, m_cq)) { +- return std::pair(false, call); +- } +- return std::pair(true, call); +- })); +-} +- +-// Iterate the calls that are timeout and retry them +-void SandboxerClientMonitor::DispatchDeferredCalls() +-{ +- std::unique_lock lock(m_deferredCallsMutex); +- if (m_teardown) { +- // Stop dispatching deferred calls +- return; +- } +- for (auto it = m_deferredCalls.begin(); it != m_deferredCalls.end();) { +- auto &call = (*it); +- if (call->Timeout()) { +- // If the call is timeout, we should retry +- InvokeDeferredCall(call); +- it = m_deferredCalls.erase(it); +- } else { +- it++; +- } +- } +-} +- +-// We use future to invoke the deferred call, when the future is ready, we should check the result +-void SandboxerClientMonitor::CheckCompletedFutures() +-{ +- for (auto it = m_futures.begin(); it != m_futures.end();) { +- auto &future = (*it); +- if (future.wait_for(std::chrono::seconds(0)) == std::future_status::ready) { +- auto result = future.get(); +- auto enqueued = result.first; +- auto call = result.second; +- if (!enqueued) { +- if (call != nullptr) { +- // Sandbox has been notified due to call failure in call->Call, +- // so no need to notify again +- call->MarkRemove(); +- } +- } else { +- // When the async wait is enqueued into completion queue, +- // and wait does not return error, we have no feadback +- // from the sandboxer, since async wait only return when +- // sandbox exited or some errors happened. +- // Therefore, one way to assume that the wait call suceeded +- // is that check the client status. If the client goes alive, +- // we assume the wait call succeeded. +- if (IsAlive()) { +- // The future is responsible to enqueue the call +- // into completion queue. So there is still a chance +- // that before we check future status here, +- // the call in completion queue has already finished, +- // and the callback has been invoked with OnSandboxPending +- // or OnSandboxExit in the HandleResponse function. +- // In this case, the OnSandboxReady will overwrite the +- // status, but it is ok, because: +- // 1. If OnSandboxPending has been invoked, +- // retry will happen pretty soon, and the +- // callback will be invoked again. +- // 2. If OnSandboxExit has been invoked, the caller +- // should check the sandbox status in the OnSandboxReady +- // callback, and it will find out the sandbox has exited, +- // and not set sandbox to ready status. +- call->SandboxReadyCallback(); +- call->ResetRetryTimes(); +- } +- } +- it = m_futures.erase(it); +- } else { +- it++; +- } +- } +-} +- +-void SandboxerClientMonitor::ClearDeferredCalls() +-{ +- std::unique_lock lock(m_deferredCallsMutex); +- m_deferredCalls.clear(); +-} +- +-void SandboxerClientMonitor::ClearAllCalls() +-{ +- std::unique_lock lock(m_callsMutex); +- for (auto &call : m_calls) { +- delete call; +- } +- m_calls.clear(); +-} +- +-void SandboxerClientMonitor::Cleanup() +-{ +- for (auto &future : m_futures) { +- future.wait(); +- } +- m_futures.clear(); +- ClearDeferredCalls(); +- ClearAllCalls(); +-} +- +-/** +- * Thread for handling completion queue. +- */ +-void SandboxerClientMonitor::AsyncCompleteRpcThread() +-{ +- void *got_tag; +- bool ok = false; +- SandboxerAsyncWaitStatus waitStatus; +- INFO("Start thread to monitor wait call completion queue for sandboxer, sandboxer: %s", +- m_sandboxer.c_str()); +- +- pthread_setname_np(pthread_self(), "SandboxerAsyncWaitThread"); +- +- // Next only return false when the completion queue is shutdown and +- // the queue is fully drained +- while (m_cq.Next(&got_tag, &ok)) { +- if (got_tag == nullptr || m_teardown) { +- // The completion queue is shutdown +- // The calls will be cleaned up by the cleanup function +- break; +- } +- auto call = static_cast(got_tag); +- waitStatus = call->HandleResponse(); +- if (waitStatus == SANDBOXER_ASYNC_WAIT_STATUS_RETRY) { +- AddDeferredCall(call); +- continue; +- } +- // The reason for not deleting the call here is that +- // while the call is being handled in this thread, +- // the call object could still possibly be referenced in the future +- // that has not been checked yet by the monitor thread. This could happen +- // especially when the completion queue is shutdown. +- call->MarkRemove(); +- // Should notify deferred thread to clean up the call +- m_deferredCallsCond.notify_one(); +- } +- INFO("Completion queue is shutdown, wait call monitor thread exit for sandboxer: %s", +- m_sandboxer.c_str()); +-} +- +-/** +- * Delete the calls that are marked to be removed. +- */ +-void SandboxerClientMonitor::DeleteRemovedCalls() +-{ +- std::unique_lock lock(m_callsMutex); +- for (auto it = m_calls.begin(); it != m_calls.end();) { +- auto &call = (*it); +- if (call->ToRemove()) { +- delete call; +- it = m_calls.erase(it); +- } else { +- it++; +- } +- } +-} +- +-/** +- * Thread for handling deferred retry calls and cleanup. +- */ +-void SandboxerClientMonitor::MonitorThread() +-{ +- INFO("Start wait call monitoring thread, sandboxer: %s", +- m_sandboxer.c_str()); +- pthread_setname_np(pthread_self(), "SandboxerMonitorThread"); +- while (!m_teardown) { +- // 1. Clean up futures that are ready +- CheckCompletedFutures(); +- // 2. Delete the calls that are marked to be removed +- DeleteRemovedCalls(); +- // 3. If deferred queue is empty, wait for the condition signal +- WaitForDeferredCall(); +- // 4. We have deferred calls in the queue, deferred for 200 ms +- std::this_thread::sleep_for(std::chrono::milliseconds(DEFERRED_QUEUE_CHECK_INTERVAL)); +- // 5. Dispatch the deferred calls +- DispatchDeferredCalls(); +- } +- // Cleanup the queue +- Cleanup(); +- INFO("Start wait call monitoring thread, sandboxer: %s", m_sandboxer.c_str()); +-} +- +-} // namespace sandbox +\ No newline at end of file +diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.h b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.h +deleted file mode 100644 +index b5740b44..00000000 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.h ++++ /dev/null +@@ -1,85 +0,0 @@ +-/****************************************************************************** +- * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: xuxuepeng +- * Create: 2023-07-28 +- * Description: Sandboxer grpc client monitor +- ******************************************************************************/ +- +-#ifndef DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_SANDBOXER_MONITOR_H +-#define DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_SANDBOXER_MONITOR_H +- +-#include +-#include +-#include +-#include +- +-#include "grpc_async_wait_call.h" +- +-namespace sandbox { +- +-/** +- * SandboxerClientMonitor is used to monitor the async wait call. +- * It will start two threads, one for monitoring the completion queue, +- * the other for retrying the async wait call. +- * The lifecycle of SandboxerAsyncWaitCall object is managed in the following way: +- * 1. When the async call first called, it will be directly passed into completion queue. +- * 2. If the call status received from completion queue is SANDBOXER_ASYNC_WAIT_STATUS_RETRY, +- * the call will be enqueued to m_deferredCalls, otherwise it will be deleted. +- * 3. When the deferred duration is reached for the call, it will be retried, and passed to +- * completion queue again. +- */ +-class SandboxerClientMonitor { +-public: +- SandboxerClientMonitor(std::shared_ptr channel, const std::string &sandboxer); +- ~SandboxerClientMonitor() = default; +- +- auto Monitor(SandboxerAsyncWaitCall *call) -> bool; +- void Start(); +- void Stop(); +-private: +- auto IsAlive() -> bool; +- void AddDeferredCall(SandboxerAsyncWaitCall *call); +- void WaitForDeferredCall(); +- void InvokeDeferredCall(SandboxerAsyncWaitCall *call); +- void DispatchDeferredCalls(); +- void AsyncCompleteRpcThread(); +- void MonitorThread(); +- void CheckCompletedFutures(); +- void DeleteRemovedCalls(); +- void ClearDeferredCalls(); +- void ClearAllCalls(); +- void Cleanup(); +- +- std::thread m_cqThread; +- std::thread m_deferredThread; +- std::unique_ptr m_stub; +- std::shared_ptr m_channel; +- std::string m_sandboxer; +- // Completion queue is thread safe, no mutex needed +- grpc::CompletionQueue m_cq; +- // Vector for holding all the calls for monitoring +- std::vector m_calls; +- std::mutex m_callsMutex; +- // Use to indicate whether +- bool m_teardown; +- // Vector for holding all the retry calls +- std::vector m_deferredCalls; +- std::mutex m_deferredCallsMutex; +- std::condition_variable m_deferredCallsCond; +- +- // Vector for holding all the futures in flight +- // No need to lock, only used in m_deferredThread thread +- std::vector>> m_futures; +-}; +- +-} // namespace sandbox +- +-#endif // DAEMON_SANDBOX_CONTROLLER_SANDBOXER_CLIENT_GRPC_SANDBOXER_MONITOR_H +\ No newline at end of file +diff --git a/src/daemon/sandbox/controller/controller_manager.cc b/src/daemon/sandbox/controller_manager.cc +similarity index 98% +rename from src/daemon/sandbox/controller/controller_manager.cc +rename to src/daemon/sandbox/controller_manager.cc +index 91c98d26..947f2d19 100644 +--- a/src/daemon/sandbox/controller/controller_manager.cc ++++ b/src/daemon/sandbox/controller_manager.cc +@@ -57,9 +57,6 @@ bool ControllerManager::Init(Errors &error) + + bool ControllerManager::Cleanup(Errors &error) + { +- for (auto &it : m_controllers) { +- it.second->Destroy(); +- } + return true; + } + +diff --git a/src/daemon/sandbox/controller/controller_manager.h b/src/daemon/sandbox/controller_manager.h +similarity index 100% +rename from src/daemon/sandbox/controller/controller_manager.h +rename to src/daemon/sandbox/controller_manager.h +diff --git a/src/daemon/sandbox/sandbox.cc b/src/daemon/sandbox/sandbox.cc +index 97b77f22..3715e5e0 100644 +--- a/src/daemon/sandbox/sandbox.cc ++++ b/src/daemon/sandbox/sandbox.cc +@@ -1098,11 +1098,6 @@ auto Sandbox::GetNetworkSettingsPath() -> std::string + return m_rootdir + std::string("/") + NETWORK_SETTINGS_JSON; + } + +-auto Sandbox::GetTasksJsonPath() -> std::string +-{ +- return m_rootdir + std::string("/") + SANDBOX_TASKS_JSON; +-} +- + void Sandbox::FillSandboxMetadata(sandbox_metadata* metadata, Errors &error) + { + std::string jsonStr; +@@ -1123,214 +1118,4 @@ void Sandbox::FillSandboxMetadata(sandbox_metadata* metadata, Errors &error) + + metadata->sandbox_config_json = util_strdup_s(jsonStr.c_str()); + } +- +-auto Sandbox::AddTaskById(const char *task_id, sandbox_task *task) -> bool +-{ +- +- std::string taskId = std::string(task_id); +- auto iter = m_tasks.find(taskId); +- +- if (iter != m_tasks.end()) { +- ERROR("Failed to add exits sandbox task %s for sandbox: %s", +- task_id, m_id.c_str()); +- return false; +- } +- m_tasks[taskId] = std::make_shared(task); +- return true; +-} +- +-auto Sandbox::ReadSandboxTasksJson() -> sandbox_tasks * +-{ +- const std::string path = GetTasksJsonPath(); +- __isula_auto_free parser_error err = nullptr; +- sandbox_tasks *tasksArray = nullptr; +- +- ReadGuard lock(m_tasksMutex); +- tasksArray = sandbox_tasks_parse_file(path.c_str(), nullptr, &err); +- if (tasksArray == nullptr) { +- WARN("Failed to read %s tasks json: %s", path.c_str(), err); +- } +- return tasksArray; +-} +- +-auto Sandbox::WriteSandboxTasksJson(std::string &tasks_json) -> bool +-{ +- int nret = 0; +- const std::string path = GetTasksJsonPath(); +- +- WriteGuard lock(m_tasksMutex); +- nret = util_atomic_write_file(path.c_str(), tasks_json.c_str(), tasks_json.size(), CONFIG_FILE_MODE, false); +- if (nret != 0) { +- SYSERROR("Failed to write file %s", path.c_str()); +- } +- return nret == 0; +-} +- +-auto Sandbox::DeleteSandboxTasksJson() -> bool +-{ +- int get_err = 0; +- const std::string path = GetTasksJsonPath(); +- +- WriteGuard lock(m_tasksMutex); +- if (util_fileself_exists(path.c_str()) && +- !util_force_remove_file(path.c_str(), &get_err)) { +- errno = get_err; +- SYSERROR("Failed to remove file %s", path.c_str()); +- return false; +- } +- +- return true; +-} +- +-void Sandbox::AddSandboxTasksByArray(sandbox_tasks *tasksArray) +-{ +- size_t i; +- +- WriteGuard lock(m_tasksMutex); +- for (i = 0; i < tasksArray->tasks_len; i++) { +- if (!AddTaskById(tasksArray->tasks[i]->task_id, tasksArray->tasks[i])) { +- return; +- } +- tasksArray->tasks[i] = nullptr; +- } +- tasksArray->tasks_len = 0; +-} +- +-void Sandbox::LoadSandboxTasks() +-{ +- sandbox_tasks *tasksArray = nullptr; +- +- tasksArray = ReadSandboxTasksJson(); +- if (tasksArray == nullptr) { +- return; +- } +- +- AddSandboxTasksByArray(tasksArray); +- +- free_sandbox_tasks(tasksArray); +-} +- +-auto Sandbox::SaveSandboxTasks() -> bool +-{ +- std::string tasks_json; +- +- if (m_tasks.empty()) { +- return DeleteSandboxTasksJson(); +- } +- +- tasks_json = GetAnySandboxTasks(); +- if (tasks_json.empty()) { +- ERROR("Failed to get sandbox tasks json for sandbox: '%s'", m_id.c_str()); +- return false; +- } +- +- return WriteSandboxTasksJson(tasks_json); +-} +- +-auto Sandbox::AddSandboxTasks(sandbox_task *task) -> bool +-{ +- if (task == nullptr) { +- return true; +- } +- if (task->task_id == nullptr) { +- return false; +- } +- +- WriteGuard lock(m_tasksMutex); +- +- return AddTaskById(task->task_id, task); +-} +- +-auto Sandbox::GetAnySandboxTasks() -> std::string +-{ +- __isula_auto_free parser_error err = nullptr; +- sandbox_tasks tasksArray = { 0 }; +- size_t i = 0; +- __isula_auto_free char *tasks_json = nullptr; +- +- tasksArray.tasks = (sandbox_task **)util_smart_calloc_s(sizeof(sandbox_task *), m_tasks.size()); +- if (tasksArray.tasks == nullptr) { +- SYSERROR("Out of memory."); +- return std::string(""); +- } +- +- ReadGuard lock(m_tasksMutex); +- for (auto const& [_, val] : m_tasks) { +- /* +- * We ignore that the processes are modified +- * when we generate tasks json string. +- * Because no matter whether a process is deleted or added, +- * the Update of sandbox api will be called eventually. +- * +- * And we ignore that the task is freed after we do GetTask(). +- * Because the only way to free task is DeleteSandboxTasks() +- * which needs write lock of m_tasksMutex. +- */ +- tasksArray.tasks[i] = val->GetTask(); +- i++; +- } +- tasksArray.tasks_len = m_tasks.size(); +- +- tasks_json = sandbox_tasks_generate_json(&tasksArray, nullptr, &(err)); +- if (tasks_json == nullptr || strlen(tasks_json) == 0) { +- ERROR("Failed to get sandbox tasks json for sandbox: '%s'", m_id.c_str()); +- free(tasksArray.tasks); +- return std::string(""); +- } +- +- free(tasksArray.tasks); +- return std::string(tasks_json); +-} +- +-void Sandbox::DeleteSandboxTasks(const char *containerId) +-{ +- if (containerId == nullptr) { +- return; +- } +- +- std::string taskId = std::string(containerId); +- +- WriteGuard lock(m_tasksMutex); +- auto iter = m_tasks.find(taskId); +- if (iter == m_tasks.end()) { +- return; +- } +- m_tasks.erase(iter); +-} +- +-auto Sandbox::AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool +-{ +- if (containerId == nullptr || processes == nullptr) { +- ERROR("Empty args."); +- return false; +- } +- +- std::string taskId = std::string(containerId); +- +- ReadGuard lock(m_tasksMutex); +- auto iter = m_tasks.find(taskId); +- if (iter == m_tasks.end()) { +- SYSERROR("Failed to find container %s", containerId); +- return false; +- } +- +- return iter->second->AddSandboxTasksProcess(processes); +-} +- +-void Sandbox::DeleteSandboxTasksProcess(const char *containerId, const char *execId) +-{ +- if (containerId == nullptr || execId == nullptr) { +- return; +- } +- +- std::string taskId = std::string(containerId); +- +- ReadGuard lock(m_tasksMutex); +- auto iter = m_tasks.find(taskId); +- if (iter == m_tasks.end()) { +- return; +- } +- iter->second->DeleteSandboxTasksProcess(execId); +-} +- + } +\ No newline at end of file +diff --git a/src/daemon/sandbox/sandbox.h b/src/daemon/sandbox/sandbox.h +index 437b6113..415406ff 100644 +--- a/src/daemon/sandbox/sandbox.h ++++ b/src/daemon/sandbox/sandbox.h +@@ -141,13 +141,13 @@ public: + void Status(runtime::v1::PodSandboxStatus &status); + + // for sandbox api update +- void LoadSandboxTasks(); +- auto SaveSandboxTasks() -> bool; +- auto AddSandboxTasks(sandbox_task *task) -> bool; +- auto GetAnySandboxTasks() -> std::string; +- void DeleteSandboxTasks(const char *containerId); +- auto AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool; +- void DeleteSandboxTasksProcess(const char *containerId, const char *execId); ++ virtual void LoadSandboxTasks() = 0; ++ virtual auto SaveSandboxTasks() -> bool = 0; ++ virtual auto AddSandboxTasks(sandbox_task *task) -> bool = 0; ++ virtual auto GetAnySandboxTasks() -> std::string = 0; ++ virtual void DeleteSandboxTasks(const char *containerId) = 0; ++ virtual auto AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool = 0; ++ virtual void DeleteSandboxTasksProcess(const char *containerId, const char *execId) = 0; + + private: + auto SaveState(Errors &error) -> bool; +@@ -172,7 +172,6 @@ private: + auto GetMetadataJsonPath() -> std::string; + auto GetStatePath() -> std::string; + auto GetNetworkSettingsPath() -> std::string; +- auto GetTasksJsonPath() -> std::string; + + void FillSandboxState(sandbox_state *state); + void FillSandboxMetadata(sandbox_metadata* metadata, Errors &error); +@@ -189,12 +188,6 @@ private: + + void updateSelinuxLabels(std::string &selinuxLabels); + +- auto AddTaskById(const char *task_id, sandbox_task *task) -> bool; +- auto ReadSandboxTasksJson() -> sandbox_tasks *; +- auto WriteSandboxTasksJson(std::string &tasks_json) -> bool; +- auto DeleteSandboxTasksJson() -> bool; +- void AddSandboxTasksByArray(sandbox_tasks *tasksArray); +- + private: + // Since the cri module will operate concurrently on the sandbox instance, + // use m_mutex to ensure the correctness of the sandbox instance +@@ -230,11 +223,6 @@ private: + // vsock ports + std::mutex m_vsockPortsMutex; + std::set m_vsockPorts; +- +- // use m_tasksMutex to ensure the correctness of the tasks +- RWMutex m_tasksMutex; +- // for sandbox api update, containerId --> tasks +- std::map> m_tasks; + }; + + } // namespace sandbox +diff --git a/src/daemon/sandbox/sandbox_manager.cc b/src/daemon/sandbox/sandbox_manager.cc +index 4159993f..ba003d56 100644 +--- a/src/daemon/sandbox/sandbox_manager.cc ++++ b/src/daemon/sandbox/sandbox_manager.cc +@@ -21,8 +21,13 @@ + + #include + #include ++#include + + #include "sandbox.h" ++#ifdef ENABLE_SANDBOXER ++#include "sandboxer_sandbox.h" ++#endif ++#include "shim_sandbox.h" + #include "isulad_config.h" + #include "utils_verify.h" + #include "utils_file.h" +@@ -109,7 +114,15 @@ auto SandboxManager::CreateSandbox(const std::string &name, RuntimeInfo &info, s + return nullptr; + } + +- sandbox = std::make_shared(id, m_rootdir, m_statedir, name, info, netMode, netNsPath, sandboxConfig, image); ++#ifdef ENABLE_SANDBOXER ++ if (info.sandboxer == SHIM_CONTROLLER_NAME) { ++ sandbox = std::make_shared(id, m_rootdir, m_statedir, name, info, netMode, netNsPath, sandboxConfig, image); ++ } else { ++ sandbox = std::make_shared(id, m_rootdir, m_statedir, name, info, netMode, netNsPath, sandboxConfig, image); ++ } ++#else ++ sandbox = std::make_shared(id, m_rootdir, m_statedir, name, info, netMode, netNsPath, sandboxConfig, image); ++#endif + if (sandbox == nullptr) { + ERROR("Failed to malloc for sandbox: %s", name.c_str()); + error.Errorf("Failed to malloc for sandbox: %s", name.c_str()); +@@ -442,6 +455,25 @@ bool SandboxManager::ListAllSandboxdir(std::vector &allSubdir) + return true; + } + ++#ifdef ENABLE_SANDBOXER ++static auto IsShimSandbox(const std::string &id, const std::string &rootdir) -> bool ++{ ++ __isula_auto_free parser_error err = NULL; ++ const std::string path = rootdir + "/" + id + "/" + SANDBOX_METADATA_JSON; ++ sandbox_metadata *metadata = NULL; ++ ++ metadata = sandbox_metadata_parse_file(path.c_str(), NULL, &err); ++ if (metadata == NULL) { ++ return false; ++ } ++ ++ bool ret = (strcmp(metadata->runtime_info->sandboxer, SHIM_CONTROLLER_NAME.c_str()) == 0); ++ ++ free_sandbox_metadata(metadata); ++ return ret; ++} ++#endif ++ + auto SandboxManager::LoadSandbox(std::string &id) -> std::shared_ptr + { + std::shared_ptr sandbox = nullptr; +@@ -451,7 +483,15 @@ auto SandboxManager::LoadSandbox(std::string &id) -> std::shared_ptr + return nullptr; + } + +- sandbox = std::make_shared(id, m_rootdir, m_statedir); ++#ifdef ENABLE_SANDBOXER ++ if (IsShimSandbox(id, m_rootdir)) { ++ sandbox = std::make_shared(id, m_rootdir, m_statedir); ++ } else { ++ sandbox = std::make_shared(id, m_rootdir, m_statedir); ++ } ++#else ++ sandbox = std::make_shared(id, m_rootdir, m_statedir); ++#endif + if (sandbox == nullptr) { + ERROR("Failed to malloc for sandboxes: %s", id.c_str()); + return nullptr; +diff --git a/src/daemon/sandbox/sandbox_ops.cc b/src/daemon/sandbox/sandbox_ops.cc +index 96e541a4..f50a1033 100644 +--- a/src/daemon/sandbox/sandbox_ops.cc ++++ b/src/daemon/sandbox/sandbox_ops.cc +@@ -16,6 +16,7 @@ + + #include + #include ++#include + #include + + #include "controller_manager.h" +@@ -24,6 +25,7 @@ + #include "namespace.h" + #include "utils.h" + #include "utils_timestamp.h" ++#include "utils_array.h" + + const std::string SANDBOX_EXTENSIONS_TASKS = "extensions.tasks"; + const std::string SANDBOX_TASKS_KEY = "tasks"; +@@ -62,42 +64,30 @@ static int generate_ctrl_rootfs(sandbox_task *task, + return 0; + } + +-static int do_sandbox_prepare(std::shared_ptr &sandbox, containerd::types::Sandbox &apiSandbox) ++static int do_sandbox_update(std::shared_ptr &sandbox, sandbox_sandbox *apiSandbox) + { + Errors err; +- std::vector fields; +- +- fields.push_back(SANDBOX_EXTENSIONS_TASKS); ++ size_t fields_len = 1; ++ __isula_auto_string_array_t string_array *fields = nullptr; + +- auto controller = sandbox::ControllerManager::GetInstance()->GetController(sandbox->GetSandboxer()); +- if (nullptr == controller) { +- ERROR("Invalid sandboxer name: %s", sandbox->GetSandboxer().c_str()); ++ fields = util_string_array_new(fields_len); ++ if (fields == nullptr) { ++ ERROR("Out of memory."); + return -1; + } +- +- if (!controller->Prepare(apiSandbox, fields, err)) { +- ERROR("Failed to prepare in container controller prepare: %s", err.GetCMessage()); ++ if (util_append_string_array(fields, SANDBOX_EXTENSIONS_TASKS.c_str())) { ++ ERROR("Out of memory."); + return -1; + } + +- return 0; +-} +- +-static int do_sandbox_purge(std::shared_ptr &sandbox, containerd::types::Sandbox &apiSandbox) +-{ +- Errors err; +- std::vector fields; +- +- fields.push_back(SANDBOX_EXTENSIONS_TASKS); +- + auto controller = sandbox::ControllerManager::GetInstance()->GetController(sandbox->GetSandboxer()); + if (nullptr == controller) { + ERROR("Invalid sandboxer name: %s", sandbox->GetSandboxer().c_str()); + return -1; + } + +- if (!controller->Purge(apiSandbox, fields, err)) { +- ERROR("Failed to purge: %s", err.GetCMessage()); ++ if (!controller->Update(apiSandbox, fields, err)) { ++ ERROR("Failed to update in container controller update: %s", err.GetCMessage()); + return -1; + } + +@@ -161,40 +151,112 @@ static std::shared_ptr get_prepare_sandbox(const container_con + return sandbox; + } + +-static int init_prepare_api_sandbox(std::shared_ptr sandbox, const char *containerId, +- containerd::types::Sandbox &apiSandbox) ++static sandbox_sandbox_runtime *init_sandbox_runtime(std::shared_ptr sandbox) ++{ ++ sandbox_sandbox_runtime *runtime = nullptr; ++ ++ auto runtime_wrapper = makeUniquePtrCStructWrapper(free_sandbox_sandbox_runtime); ++ if (runtime_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ return nullptr; ++ } ++ runtime = runtime_wrapper->get(); ++ runtime->name = util_strdup_s(sandbox->GetRuntime().c_str()); ++ // Just ignore options for now ++ ++ return runtime_wrapper->move(); ++} ++ ++static json_map_string_string *init_sandbox_labels(std::shared_ptr sandbox) + { +- google::protobuf::Map *labels = apiSandbox.mutable_labels(); +- google::protobuf::Map *extensions = apiSandbox.mutable_extensions(); +- google::protobuf::Any any; +- auto created_at = new (std::nothrow) google::protobuf::Timestamp; +- auto updated_at = new (std::nothrow) google::protobuf::Timestamp; ++ json_map_string_string *labels = nullptr; ++ ++ auto labels_wrapper = makeUniquePtrCStructWrapper(free_json_map_string_string); ++ if (labels_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ return nullptr; ++ } ++ labels = labels_wrapper->get(); ++ if (append_json_map_string_string(labels, "name", sandbox->GetName().c_str()) != 0) { ++ ERROR("Out of memory"); ++ return nullptr; ++ } + +- apiSandbox.set_sandbox_id(sandbox->GetId()); +- apiSandbox.mutable_runtime()->set_name(sandbox->GetRuntime()); +- // TODO how get options +- // apiSandbox.mutable_runtime()->set_options(sandbox->GetRuntime()); +- // Just ignore spec +- (*labels)[std::string("name")] = sandbox->GetName(); +- +- *created_at = google::protobuf::util::TimeUtil::NanosecondsToTimestamp( +- sandbox->GetCreatedAt()); +- apiSandbox.set_allocated_created_at(created_at); +- *updated_at = google::protobuf::util::TimeUtil::NanosecondsToTimestamp(util_get_now_time_nanos()); +- apiSandbox.set_allocated_updated_at(updated_at); +- +- auto any_type_url = any.mutable_type_url(); +- *any_type_url = SANDBOX_TASKS_TYPEURL; +- auto any_value = any.mutable_value(); +- *any_value = sandbox->GetAnySandboxTasks(); +- if ((*any_value).empty()) { ++ return labels_wrapper->move(); ++} ++ ++static defs_map_string_object_any *init_sandbox_extensions(std::shared_ptr sandbox) ++{ ++ defs_map_string_object_any *extensions = nullptr; ++ size_t len = 1; ++ std::string task_json; ++ ++ auto extensions_wrapper = makeUniquePtrCStructWrapper(free_defs_map_string_object_any); ++ if (extensions_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ return nullptr; ++ } ++ extensions = extensions_wrapper->get(); ++ extensions->keys = (char **)util_smart_calloc_s(sizeof(char *), len); ++ if (extensions->keys == nullptr) { ++ ERROR("Out of memory."); ++ return nullptr; ++ } ++ extensions->len = len; ++ extensions->values = (defs_map_string_object_any_element **) ++ util_smart_calloc_s(sizeof(defs_map_string_object_any_element *), len); ++ if (extensions->values == nullptr) { ++ ERROR("Out of memory."); ++ return nullptr; ++ } ++ extensions->values[0] = (defs_map_string_object_any_element *) ++ util_common_calloc_s(sizeof(defs_map_string_object_any_element)); ++ if (extensions->values[0] == nullptr) { ++ ERROR("Out of memory."); ++ return nullptr; ++ } ++ extensions->values[0]->element = (defs_any *)util_common_calloc_s(sizeof(defs_any)); ++ if (extensions->values[0]->element == nullptr) { ++ ERROR("Out of memory."); ++ return nullptr; ++ } ++ ++ extensions->keys[0] = util_strdup_s(SANDBOX_TASKS_KEY.c_str()); ++ task_json = sandbox->GetAnySandboxTasks(); ++ if (task_json.empty()) { + ERROR("Failed to get any sandbox tasks"); +- return -1; ++ return nullptr; + } +- DEBUG("Get any sandbox tasks %s", (*any_value).c_str()); +- (*extensions)[SANDBOX_TASKS_KEY] = any; ++ DEBUG("Get any sandbox tasks %s", task_json.c_str()); ++ extensions->values[0]->element->type_url = util_strdup_s(SANDBOX_TASKS_TYPEURL.c_str()); ++ extensions->values[0]->element->value = reinterpret_cast(util_strdup_s(task_json.c_str())); ++ extensions->values[0]->element->value_len = strlen(task_json.c_str()); ++ ++ return extensions_wrapper->move(); ++} + +- apiSandbox.set_sandboxer(sandbox->GetSandboxer()); ++static int init_api_sandbox(std::shared_ptr sandbox, sandbox_sandbox *apiSandbox) ++{ ++ apiSandbox->sandbox_id = util_strdup_s(sandbox->GetId().c_str()); ++ apiSandbox->runtime = init_sandbox_runtime(sandbox); ++ if (apiSandbox->runtime == nullptr) { ++ ERROR("Failed to init sandbox runtime"); ++ return -1; ++ } ++ // Just ignore spec ++ apiSandbox->labels = init_sandbox_labels(sandbox); ++ if (apiSandbox->labels == nullptr) { ++ ERROR("Failed to init sandbox runtime"); ++ return -1; ++ } ++ apiSandbox->created_at = sandbox->GetCreatedAt(); ++ apiSandbox->updated_at = util_get_now_time_nanos(); ++ apiSandbox->extensions = init_sandbox_extensions(sandbox); ++ if (apiSandbox->extensions == nullptr) { ++ ERROR("Failed to init sandbox runtime"); ++ return -1; ++ } ++ apiSandbox->sandboxer = util_strdup_s(sandbox->GetSandboxer().c_str()); + + return 0; + } +@@ -204,7 +266,7 @@ int sandbox_prepare_container(const container_config_v2_common_config *config, + const char * console_fifos[], bool tty) + { + sandbox_task *task = nullptr; +- containerd::types::Sandbox apiSandbox; ++ sandbox_sandbox *apiSandbox = nullptr; + int ret = -1; + + INFO("Prepare container for sandbox"); +@@ -220,20 +282,28 @@ int sandbox_prepare_container(const container_config_v2_common_config *config, + return -1; + } + +- task = (sandbox_task *)util_common_calloc_s(sizeof(sandbox_task)); +- if (task == nullptr) { +- ERROR("Out of memory."); ++ auto apiSandbox_wrapper = makeUniquePtrCStructWrapper(free_sandbox_sandbox); ++ if (apiSandbox_wrapper == nullptr) { ++ ERROR("Out of memory"); + return -1; + } ++ apiSandbox = apiSandbox_wrapper->get(); ++ auto task_wrapper = makeUniquePtrCStructWrapper(free_sandbox_task); ++ if (task_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ task = task_wrapper->get(); ++ + task->task_id = util_strdup_s(config->id); + task->spec = clone_oci_runtime_spec(oci_spec); + if (task->spec == nullptr) { + ERROR("Out of memory."); +- goto free_out; ++ return -1; + } + if (generate_ctrl_rootfs(task, config) != 0) { + ERROR("Invalid rootfs"); +- goto free_out; ++ return -1; + } + task->stdin = util_strdup_s((nullptr == console_fifos[0]) ? "" : console_fifos[0]); + task->stdout = util_strdup_s((nullptr == console_fifos[1]) ? "" : console_fifos[1]); +@@ -241,15 +311,15 @@ int sandbox_prepare_container(const container_config_v2_common_config *config, + + if (!sandbox->AddSandboxTasks(task)) { + ERROR("Failed to add sandbox %s task.", config->id); +- goto free_out; ++ return -1; + } +- task = nullptr; +- ret = init_prepare_api_sandbox(sandbox, config->id, apiSandbox); ++ task = task_wrapper->move(); ++ ret = init_api_sandbox(sandbox, apiSandbox); + if (ret != 0) { + ERROR("Failed to init %s api sandbox.", config->id); + goto del_out; + } +- ret = do_sandbox_prepare(sandbox, apiSandbox); ++ ret = do_sandbox_update(sandbox, apiSandbox); + + del_out: + if (ret != 0) { +@@ -259,8 +329,7 @@ del_out: + ERROR("Failed to Save %s sandbox tasks.", config->id); + ret = -1; + } +-free_out: +- free_sandbox_task(task); ++ + return ret; + } + +@@ -269,7 +338,7 @@ int sandbox_prepare_exec(const container_config_v2_common_config *config, + const char * console_fifos[], bool tty) + { + sandbox_process *process = nullptr; +- containerd::types::Sandbox apiSandbox; ++ sandbox_sandbox *apiSandbox = nullptr; + int ret = -1; + + INFO("Prepare exec for container in sandbox"); +@@ -285,16 +354,24 @@ int sandbox_prepare_exec(const container_config_v2_common_config *config, + return -1; + } + +- process = (sandbox_process *)util_common_calloc_s(sizeof(sandbox_process)); +- if (process == nullptr) { +- ERROR("Out of memory."); ++ auto apiSandbox_wrapper = makeUniquePtrCStructWrapper(free_sandbox_sandbox); ++ if (apiSandbox_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ apiSandbox = apiSandbox_wrapper->get(); ++ auto process_wrapper = makeUniquePtrCStructWrapper(free_sandbox_process); ++ if (process_wrapper == nullptr) { ++ ERROR("Out of memory"); + return -1; + } ++ process = process_wrapper->get(); ++ + process->exec_id = util_strdup_s(exec_id); + process->spec = clone_defs_process(process_spec); + if (process->spec == nullptr) { + ERROR("Out of memory."); +- goto free_out; ++ return -1; + } + process->stdin = util_strdup_s((nullptr == console_fifos[0]) ? "" : console_fifos[0]); + process->stdout = util_strdup_s((nullptr == console_fifos[1]) ? "" : console_fifos[1]); +@@ -302,15 +379,15 @@ int sandbox_prepare_exec(const container_config_v2_common_config *config, + + if (!sandbox->AddSandboxTasksProcess(config->id, process)) { + ERROR("Failed to add sandbox %s process.", config->id); +- goto free_out; ++ return -1; + } +- process = nullptr; +- ret = init_prepare_api_sandbox(sandbox, config->id, apiSandbox); ++ process = process_wrapper->move(); ++ ret = init_api_sandbox(sandbox, apiSandbox); + if (ret != 0) { + ERROR("Failed to init %s api sandbox.", config->id); + goto del_out; + } +- ret = do_sandbox_prepare(sandbox, apiSandbox); ++ ret = do_sandbox_update(sandbox, apiSandbox); + + del_out: + if (ret != 0) { +@@ -320,14 +397,13 @@ del_out: + ERROR("Failed to Save %s sandbox tasks.", config->id); + ret = -1; + } +-free_out: +- free_sandbox_process(process); ++ + return ret; + } + + int sandbox_purge_container(const container_config_v2_common_config *config) + { +- containerd::types::Sandbox apiSandbox; ++ sandbox_sandbox *apiSandbox = nullptr; + + INFO("Purge container for sandbox"); + +@@ -337,22 +413,29 @@ int sandbox_purge_container(const container_config_v2_common_config *config) + return -1; + } + ++ auto apiSandbox_wrapper = makeUniquePtrCStructWrapper(free_sandbox_sandbox); ++ if (apiSandbox_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ apiSandbox = apiSandbox_wrapper->get(); ++ + sandbox->DeleteSandboxTasks(config->id); + if (!sandbox->SaveSandboxTasks()) { + ERROR("Failed to Save %s sandbox tasks.", config->id); + return -1; + } + +- if (init_prepare_api_sandbox(sandbox, config->id, apiSandbox) != 0) { ++ if (init_api_sandbox(sandbox, apiSandbox) != 0) { + ERROR("Failed to init %s api sandbox.", config->id); + return -1; + } +- return do_sandbox_purge(sandbox, apiSandbox); ++ return do_sandbox_update(sandbox, apiSandbox); + } + + int sandbox_purge_exec(const container_config_v2_common_config *config, const char *exec_id) + { +- containerd::types::Sandbox apiSandbox; ++ sandbox_sandbox *apiSandbox = nullptr; + + INFO("Purge exec for container in sandbox"); + +@@ -362,18 +445,25 @@ int sandbox_purge_exec(const container_config_v2_common_config *config, const ch + return -1; + } + ++ auto apiSandbox_wrapper = makeUniquePtrCStructWrapper(free_sandbox_sandbox); ++ if (apiSandbox_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ apiSandbox = apiSandbox_wrapper->get(); ++ + sandbox->DeleteSandboxTasksProcess(config->id, exec_id); + if (!sandbox->SaveSandboxTasks()) { + ERROR("Failed to Save %s sandbox tasks.", config->id); + return -1; + } + +- if (init_prepare_api_sandbox(sandbox, config->id, apiSandbox) != 0) { ++ if (init_api_sandbox(sandbox, apiSandbox) != 0) { + ERROR("Failed to init %s api sandbox.", exec_id); + return -1; + } + +- return do_sandbox_purge(sandbox, apiSandbox); ++ return do_sandbox_update(sandbox, apiSandbox); + } + + int sandbox_on_sandbox_exit(const char *sandbox_id, int exit_code) +diff --git a/src/daemon/sandbox/sandbox_task.cc b/src/daemon/sandbox/sandbox_task.cc +index b1efc340..4533f381 100644 +--- a/src/daemon/sandbox/sandbox_task.cc ++++ b/src/daemon/sandbox/sandbox_task.cc +@@ -91,8 +91,11 @@ void SandboxTask::DeleteSandboxTasksProcess(const char *execId) + return; + } + free_sandbox_process(m_task->processes[idx]); +- (void)memcpy((void **)&m_task->processes[idx], (void **)&m_task->processes[idx + 1], +- (m_task->processes_len - idx - 1) * sizeof(void *)); ++ m_task->processes[idx] = nullptr; ++ if (idx != (int)m_task->processes_len - 1) { ++ (void)memcpy((void **)&m_task->processes[idx], (void **)&m_task->processes[idx + 1], ++ (m_task->processes_len - idx - 1) * sizeof(void *)); ++ } + m_task->processes_len--; + } + +diff --git a/src/daemon/sandbox/sandboxer/CMakeLists.txt b/src/daemon/sandbox/sandboxer/CMakeLists.txt +new file mode 100755 +index 00000000..2b0607e0 +--- /dev/null ++++ b/src/daemon/sandbox/sandboxer/CMakeLists.txt +@@ -0,0 +1,15 @@ ++# get current directory sources files ++aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} sandboxer_sandbox_srcs) ++ ++add_subdirectory(controller) ++ ++set(SANDBOXER_SANDBOX_SRCS ++ ${sandboxer_sandbox_srcs} ++ ${CONTROLLER_SANDBOXER_SRCS} ++ PARENT_SCOPE ++ ) ++set(SANDBOXER_SANDBOX_INCS ++ ${CMAKE_CURRENT_SOURCE_DIR} ++ ${CONTROLLER_SANDBOXER_INCS} ++ PARENT_SCOPE ++ ) +diff --git a/src/daemon/sandbox/controller/sandboxer/CMakeLists.txt b/src/daemon/sandbox/sandboxer/controller/CMakeLists.txt +similarity index 100% +rename from src/daemon/sandbox/controller/sandboxer/CMakeLists.txt +rename to src/daemon/sandbox/sandboxer/controller/CMakeLists.txt +diff --git a/src/daemon/sandbox/sandboxer/controller/client/CMakeLists.txt b/src/daemon/sandbox/sandboxer/controller/client/CMakeLists.txt +new file mode 100755 +index 00000000..6ecd350b +--- /dev/null ++++ b/src/daemon/sandbox/sandboxer/controller/client/CMakeLists.txt +@@ -0,0 +1,12 @@ ++# get current directory sources files ++aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} sandbox_controller_sandboxer_client_srcs) ++ ++set(CONTROLLER_SANDBOXER_CLIENT_SRCS ++ ${sandbox_controller_sandboxer_client_srcs} ++ PARENT_SCOPE ++ ) ++ ++set(CONTROLLER_SANDBOXER_CLIENT_INCS ++ ${CMAKE_CURRENT_SOURCE_DIR} ++ PARENT_SCOPE ++ ) +diff --git a/src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.cc b/src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.cc +new file mode 100644 +index 00000000..d7ff76d7 +--- /dev/null ++++ b/src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.cc +@@ -0,0 +1,463 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: xuxuepeng ++ * Create: 2023-07-10 ++ * Description: Sandboxer grpc client ++ ******************************************************************************/ ++ ++#include "grpc_sandboxer_client.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "utils.h" ++#include "cstruct_wrapper.h" ++#include "transform.h" ++#include "sandbox_manager.h" ++ ++namespace sandbox { ++ ++SandboxerClient::SandboxerClient(const std::string &sandboxer, const std::string &address): ++ m_sandboxer(sandboxer), m_address(address) ++{ ++ std::string unixPrefix(UNIX_SOCKET_PREFIX); ++ ++ // Only support unix domain socket ++ if (m_address.compare(0, unixPrefix.length(), unixPrefix) == 0) { ++ m_address = m_address.substr(unixPrefix.length()); ++ } ++ m_controller_handle = sandbox_api_build_controller(m_sandboxer.c_str(), m_address.c_str()); ++ if (m_controller_handle == nullptr) { ++ ERROR("Failed to create sandboxer client, sandboxer: %s, address: %s", m_sandboxer.c_str(), m_address.c_str()); ++ } ++} ++ ++auto SandboxerClient::InitMountInfo(sandbox_mount &m, const ControllerMountInfo &mountInfo) -> int ++{ ++ m.type = util_strdup_s(mountInfo.type.c_str()); ++ m.source = util_strdup_s(mountInfo.source.c_str()); ++ m.target = util_strdup_s(mountInfo.destination.c_str()); ++ ++ size_t mount_options_len = mountInfo.options.size(); ++ int ret = 0; ++ for (size_t j = 0; j < mount_options_len; j++) { ++ ret = util_array_append(&(m.options), mountInfo.options[j].c_str()); ++ if (ret != 0) { ++ ERROR("append mount options to array failed"); ++ return -1; ++ } ++ m.options_len++; ++ } ++ return 0; ++} ++ ++auto SandboxerClient::InitCreateRequest(sandbox_create_request &request, ++ const std::string &sandboxId, ++ const ControllerCreateParams ¶ms) -> bool ++{ ++ if (params.config == nullptr) { ++ ERROR("Sandboxer controller create request failed, config is null"); ++ return false; ++ } ++ request.sandboxer = util_strdup_s(m_sandboxer.c_str()); ++ request.sandbox_id = util_strdup_s(sandboxId.c_str()); ++ std::string encoded; ++ if (!params.config->SerializeToString(&encoded)) { ++ ERROR("Failed to serialize config"); ++ return false; ++ } ++ request.options = (defs_any *)util_common_calloc_s(sizeof(defs_any)); ++ if (request.options == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ request.options->value = (uint8_t *)util_common_calloc_s(encoded.size()); ++ if (request.options == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ (void)memcpy(request.options->value, encoded.c_str(), encoded.size()); ++ request.options->value_len = encoded.size(); ++ request.netns_path = util_strdup_s(params.netNSPath.c_str()); ++ sandbox_mount **mounts = NULL; ++ size_t mounts_len = params.mounts.size(); ++ if (mounts_len > 0) { ++ request.rootfs = (sandbox_mount**)util_common_calloc_s(mounts_len * sizeof(sandbox_mount *)); ++ if (request.rootfs == nullptr) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ for (const auto &entry : params.mounts) { ++ if (entry != nullptr) { ++ sandbox_mount *m = (sandbox_mount *)util_common_calloc_s(sizeof(sandbox_mount)); ++ if (m == NULL) { ++ ERROR("Out of memory"); ++ return false; ++ } ++ if (InitMountInfo(*m, *entry) != 0) { ++ ERROR("Failed to init mount info"); ++ free(m); ++ return false; ++ } ++ mounts[request.rootfs_len++] = m; ++ m = NULL; ++ } ++ } ++ } ++ return true; ++} ++ ++auto SandboxerClient::Create(const std::string &sandboxId, const ControllerCreateParams ¶ms, Errors &error) -> bool ++{ ++ sandbox_create_request *request { nullptr }; ++ sandbox_create_response *response { nullptr }; ++ ++ auto create_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_create_request); ++ if (create_request_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ error.SetError("Out of memory"); ++ return false; ++ } ++ request = create_request_wrapper->get(); ++ ++ auto create_response_wrapper = makeUniquePtrCStructWrapper(free_sandbox_create_response); ++ if (create_response_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ error.SetError("Out of memory"); ++ return false; ++ } ++ response = create_response_wrapper->get(); ++ ++ if (!InitCreateRequest(*request, sandboxId, params)) { ++ ERROR("Failed to init create request for sandboxer create request"); ++ error.SetError("Failed to init create request for sandboxer create request"); ++ return false; ++ } ++ int ret = sandbox_api_create(m_controller_handle, request, response); ++ if (ret != 0) { ++ ERROR("Failed to create sandbox"); ++ error.SetError("Failed to create sandbox"); ++ return false; ++ } ++ ++ return true; ++} ++ ++void SandboxerClient::StartResponseToSandboxInfo(sandbox_start_response &response, ++ ControllerSandboxInfo &sandboxInfo) ++{ ++ sandboxInfo.id = std::string(response.sandbox_id); ++ sandboxInfo.pid = response.pid; ++ sandboxInfo.createdAt = response.created_at; ++ sandboxInfo.taskAddress = std::string(response.address); ++ sandboxInfo.version = response.version; ++ Transform::JsonMapToProtobufMapForString(response.labels, sandboxInfo.labels); ++} ++ ++auto SandboxerClient::Start(const std::string &sandboxId, ControllerSandboxInfo &sandboxInfo, Errors &error) -> bool ++{ ++ sandbox_start_request *request { nullptr }; ++ sandbox_start_response *response { nullptr }; ++ ++ auto start_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_start_request); ++ if (start_request_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ error.SetError("Out of memory"); ++ return false; ++ } ++ request = start_request_wrapper->get(); ++ ++ auto start_response_wrapper = makeUniquePtrCStructWrapper(free_sandbox_start_response); ++ if (start_response_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ error.SetError("Out of memory"); ++ return false; ++ } ++ response = start_response_wrapper->get(); ++ ++ request->sandboxer = util_strdup_s(m_sandboxer.c_str()); ++ request->sandbox_id = util_strdup_s(sandboxId.c_str()); ++ ++ int ret = sandbox_api_start(m_controller_handle, request, response); ++ if (ret != 0) { ++ ERROR("Failed to start sandbox"); ++ error.SetError("Failed to start sandbox"); ++ return false; ++ } ++ ++ StartResponseToSandboxInfo(*response, sandboxInfo); ++ ++ return true; ++} ++ ++void SandboxerClient::InitUpdateRequest(sandbox_update_request &request, ++ sandbox_sandbox *apiSandbox, string_array *fields) ++{ ++ request.sandbox_id = util_strdup_s(apiSandbox->sandbox_id); ++ request.sandboxer = util_strdup_s(apiSandbox->sandboxer); ++ request.sandbox = apiSandbox; ++ request.fields = fields->items; ++ request.fields_len = fields->len; ++} ++ ++auto SandboxerClient::Update(sandbox_sandbox *apiSandbox, string_array *fields, Errors &error) -> bool ++{ ++ sandbox_update_request *request { nullptr }; ++ ++ auto update_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_update_request); ++ if (update_request_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ error.SetError("Out of memory"); ++ return false; ++ } ++ request = update_request_wrapper->get(); ++ ++ InitUpdateRequest(*request, apiSandbox, fields); ++ int ret = sandbox_api_update(m_controller_handle, request); ++ request->sandbox = nullptr; ++ request->fields = nullptr; ++ request->fields_len = 0; ++ if (ret != 0) { ++ ERROR("Failed to update sandbox"); ++ error.SetError("Failed to update sandbox"); ++ return false; ++ } ++ ++ return true; ++} ++ ++void SandboxerClient::PlatformResponseToPlatformInfo(sandbox_platform_response &response, ++ ControllerPlatformInfo &platformInfo) ++{ ++ platformInfo.os = std::string(response.os); ++ platformInfo.arch = std::string(response.architecture); ++ platformInfo.variant = std::string(response.variant); ++} ++ ++auto SandboxerClient::Platform(const std::string &sandboxId, ControllerPlatformInfo &platformInfo, ++ Errors &error) -> bool ++{ ++ sandbox_platform_request *request { nullptr }; ++ sandbox_platform_response *response { nullptr }; ++ ++ auto platform_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_platform_request); ++ if (platform_request_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ error.SetError("Out of memory"); ++ return false; ++ } ++ request = platform_request_wrapper->get(); ++ ++ auto platform_response_wrapper = makeUniquePtrCStructWrapper(free_sandbox_platform_response); ++ if (platform_response_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ error.SetError("Out of memory"); ++ return false; ++ } ++ response = platform_response_wrapper->get(); ++ ++ request->sandboxer = util_strdup_s(m_sandboxer.c_str()); ++ request->sandbox_id = util_strdup_s(sandboxId.c_str()); ++ int ret = sandbox_api_platform(m_controller_handle, request, response); ++ if (ret != 0) { ++ ERROR("Failed to platform sandbox"); ++ error.SetError("Failed to platform sandbox"); ++ return false; ++ } ++ ++ PlatformResponseToPlatformInfo(*response, platformInfo); ++ ++ return true; ++} ++ ++auto SandboxerClient::Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) -> bool ++{ ++ sandbox_stop_request *request { nullptr }; ++ ++ auto stop_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_stop_request); ++ if (stop_request_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ error.SetError("Out of memory"); ++ return false; ++ } ++ request = stop_request_wrapper->get(); ++ ++ request->sandboxer = util_strdup_s(m_sandboxer.c_str()); ++ request->sandbox_id = util_strdup_s(sandboxId.c_str()); ++ request->timeout_secs = timeoutSecs; ++ int ret = sandbox_api_stop(m_controller_handle, request); ++ if (ret != 0) { ++ ERROR("Failed to stop sandbox"); ++ error.SetError("Failed to stop sandbox"); ++ return false; ++ } ++ ++ return true; ++} ++ ++void SandboxerClient::StatusResponseToSandboxStatus(sandbox_status_response ++ &response, ++ ControllerSandboxStatus &sandboxStatus) ++{ ++ sandboxStatus.id = std::string(response.sandbox_id); ++ sandboxStatus.pid = response.pid; ++ sandboxStatus.state = std::string(response.state); ++ Transform::JsonMapToProtobufMapForString(response.info, sandboxStatus.info); ++ sandboxStatus.createdAt = response.created_at; ++ sandboxStatus.exitedAt = response.exited_at; ++ if (response.extra != nullptr && response.extra->value != nullptr) { ++ sandboxStatus.extra = std::string(response.extra->value, ++ response.extra->value + response.extra->value_len); ++ } else { ++ sandboxStatus.extra = std::string(""); ++ } ++ sandboxStatus.taskAddress = std::string(response.address); ++ sandboxStatus.version = response.version; ++} ++ ++auto SandboxerClient::Status(const std::string &sandboxId, bool verbose, ControllerSandboxStatus &sandboxStatus, ++ Errors &error) -> bool ++{ ++ sandbox_status_request *request { nullptr }; ++ sandbox_status_response *response { nullptr }; ++ ++ auto status_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_status_request); ++ if (status_request_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ error.SetError("Out of memory"); ++ return false; ++ } ++ request = status_request_wrapper->get(); ++ ++ auto status_response_wrapper = makeUniquePtrCStructWrapper(free_sandbox_status_response); ++ if (status_response_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ error.SetError("Out of memory"); ++ return false; ++ } ++ response = status_response_wrapper->get(); ++ ++ request->sandboxer = util_strdup_s(m_sandboxer.c_str()); ++ request->sandbox_id = util_strdup_s(sandboxId.c_str()); ++ request->verbose = verbose; ++ int ret = sandbox_api_status(m_controller_handle, request, response); ++ if (ret != 0) { ++ ERROR("Failed to status sandbox"); ++ error.SetError("Failed to status sandbox"); ++ return false; ++ } ++ ++ StatusResponseToSandboxStatus(*response, sandboxStatus); ++ ++ return true; ++} ++ ++auto SandboxerClient::Shutdown(const std::string &sandboxId, Errors &error) -> bool ++{ ++ sandbox_shutdown_request *request { nullptr }; ++ ++ auto shutdown_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_shutdown_request); ++ if (shutdown_request_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ error.SetError("Out of memory"); ++ return false; ++ } ++ request = shutdown_request_wrapper->get(); ++ ++ request->sandboxer = util_strdup_s(m_sandboxer.c_str()); ++ request->sandbox_id = util_strdup_s(sandboxId.c_str()); ++ int ret = sandbox_api_shutdown(m_controller_handle, request); ++ if (ret != 0) { ++ ERROR("Failed to shutdown sandbox"); ++ error.SetError("Failed to shutdown sandbox"); ++ return false; ++ } ++ ++ return true; ++} ++ ++static int sandbox_api_ready(const char *sandbox_id) ++{ ++ std::string sandboxId = std::string(sandbox_id); ++ auto sandbox = sandbox::SandboxManager::GetInstance()->GetSandbox(sandboxId); ++ if (nullptr == sandbox) { ++ ERROR("Sandbox not found"); ++ return -1; ++ } ++ ++ sandbox->OnSandboxReady(); ++ return 0; ++} ++ ++static int sandbox_api_pending(const char *sandbox_id) ++{ ++ std::string sandboxId = std::string(sandbox_id); ++ auto sandbox = sandbox::SandboxManager::GetInstance()->GetSandbox(sandboxId); ++ if (nullptr == sandbox) { ++ ERROR("Sandbox not found"); ++ return -1; ++ } ++ ++ sandbox->OnSandboxPending(); ++ return 0; ++} ++ ++static int sandbox_api_exit(const char *sandbox_id, const sandbox_wait_response *response) ++{ ++ ControllerExitInfo exitInfo; ++ std::string sandboxId = std::string(sandbox_id); ++ auto sandbox = sandbox::SandboxManager::GetInstance()->GetSandbox(sandboxId); ++ if (nullptr == sandbox) { ++ ERROR("Sandbox not found"); ++ return -1; ++ } ++ ++ exitInfo.exitStatus = response->exit_status; ++ exitInfo.exitedAt = response->exited_at; ++ sandbox->OnSandboxExit(exitInfo); ++ return 0; ++} ++ ++auto SandboxerClient::Wait(std::shared_ptr cb, const std::string &sandboxId, ++ Errors &error) -> bool ++{ ++ sandbox_wait_request *request { nullptr }; ++ sandbox_api_wait_callback callback; ++ ++ auto wait_request_wrapper = makeUniquePtrCStructWrapper(free_sandbox_wait_request); ++ if (wait_request_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ error.SetError("Out of memory"); ++ return false; ++ } ++ request = wait_request_wrapper->get(); ++ ++ request->sandboxer = util_strdup_s(m_sandboxer.c_str()); ++ request->sandbox_id = util_strdup_s(sandboxId.c_str()); ++ callback.ready = sandbox_api_ready; ++ callback.pending = sandbox_api_pending; ++ callback.exit = sandbox_api_exit; ++ int ret = sandbox_api_wait(m_controller_handle, request, callback); ++ if (ret != 0) { ++ ERROR("Failed to wait sandbox"); ++ error.SetError("Failed to wait sandbox"); ++ return false; ++ } ++ ++ return true; ++} ++ ++} // namespace +diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.h b/src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.h +similarity index 54% +rename from src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.h +rename to src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.h +index eeb5d7f2..d712be04 100644 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.h ++++ b/src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.h +@@ -20,15 +20,10 @@ + #include + #include + +-#include "sandbox/types/mount.pb.h" +-#include "sandbox.pb.h" +-#include "sandbox.grpc.pb.h" +-#include "controller.h" +-#include "grpc_async_wait_call.h" +-#include "grpc_sandboxer_monitor.h" ++#include + +-using containerd::types::Mount; +-using google::protobuf::Timestamp; ++#include "controller.h" ++#include "utils_array.h" + + namespace sandbox { + +@@ -38,24 +33,13 @@ public: + + ~SandboxerClient() = default; + +- void Init(Errors &error); +- +- void Destroy(); +- + auto Create(const std::string &sandboxId, const ControllerCreateParams ¶ms, Errors &error) -> bool; + + auto Start(const std::string &sandboxId, ControllerSandboxInfo &sandboxInfo, Errors &error) -> bool; + + auto Platform(const std::string &sandboxId, ControllerPlatformInfo &platformInfo, Errors &error) -> bool; + +- auto Prepare(containerd::types::Sandbox &apiSandbox, +- std::vector &fields, Errors &error) -> bool; +- +- auto Purge(containerd::types::Sandbox &apiSandbox, +- std::vector &fields, Errors &error) -> bool; +- +- auto UpdateResources(const std::string &sandboxId, const ControllerUpdateResourcesParams ¶ms, +- Errors &error) -> bool; ++ auto Update(sandbox_sandbox *apiSandbox, string_array *fields, Errors &error) -> bool; + + auto Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) -> bool; + +@@ -66,27 +50,23 @@ public: + auto Shutdown(const std::string &sandboxId, Errors &error) -> bool; + + private: +- void InitMountInfo(Mount &mount, const ControllerMountInfo &mountInfo); +- auto InitCreateRequest(containerd::services::sandbox::v1::ControllerCreateRequest &request, ++ auto InitMountInfo(sandbox_mount &m, const ControllerMountInfo &mountInfo) -> int; ++ auto InitCreateRequest(sandbox_create_request &request, + const std::string &sandboxId, + const ControllerCreateParams ¶ms) -> bool; +- void StartResponseToSandboxInfo(const containerd::services::sandbox::v1::ControllerStartResponse &response, ++ void StartResponseToSandboxInfo(sandbox_start_response &response, + ControllerSandboxInfo &sandboxInfo); +- void InitUpdateRequest(containerd::services::sandbox::v1::ControllerUpdateRequest &request, +- containerd::types::Sandbox &apiSandbox, std::vector &fields); +- // auto InitUpdateResourcesRequest(containerd::services::sandbox::v1::UpdateResourcesRequest &request, +- // const std::string &sandboxId, +- // const ControllerUpdateResourcesParams ¶ms) -> bool; +- void PlatformResponseToPlatformInfo(const containerd::services::sandbox::v1::ControllerPlatformResponse &response, ++ void InitUpdateRequest(sandbox_update_request &request, ++ sandbox_sandbox *apiSandbox, string_array *fields); ++ ++ void PlatformResponseToPlatformInfo(sandbox_platform_response &response, + ControllerPlatformInfo &platformInfo); +- void StatusResponseToSandboxStatus(const containerd::services::sandbox::v1::ControllerStatusResponse &response, ++ void StatusResponseToSandboxStatus(sandbox_status_response &response, + ControllerSandboxStatus &sandboxStatus); + protected: + std::string m_sandboxer; + std::string m_address; +- std::shared_ptr m_channel; +- std::unique_ptr m_stub; +- std::unique_ptr m_monitor; ++ ControllerHandle_t m_controller_handle; + }; + + } // namespace +diff --git a/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.cc b/src/daemon/sandbox/sandboxer/controller/sandboxer_controller.cc +similarity index 78% +rename from src/daemon/sandbox/controller/sandboxer/sandboxer_controller.cc +rename to src/daemon/sandbox/sandboxer/controller/sandboxer_controller.cc +index 70cab015..bbe52c85 100644 +--- a/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.cc ++++ b/src/daemon/sandbox/sandboxer/controller/sandboxer_controller.cc +@@ -27,15 +27,9 @@ SandboxerController::~SandboxerController() {} + + bool SandboxerController::Init(Errors &error) + { +- m_client->Init(error); + return true; + } + +-void SandboxerController::Destroy() +-{ +- m_client->Destroy(); +-} +- + bool SandboxerController::Create(const std::string &sandboxId, + const ControllerCreateParams ¶ms, + Errors &error) +@@ -61,25 +55,10 @@ std::unique_ptr SandboxerController::Platform(const std: + return platformInfo; + } + +-bool SandboxerController::Prepare(containerd::types::Sandbox &apiSandbox, +- std::vector &fields, +- Errors &error) +-{ +- return m_client->Prepare(apiSandbox, fields, error); +-} +- +-bool SandboxerController::Purge(containerd::types::Sandbox &apiSandbox, +- std::vector &fields, +- Errors &error) +-{ +- return m_client->Purge(apiSandbox, fields, error); +-} +- +-bool SandboxerController::UpdateResources(const std::string &sandboxId, +- const ControllerUpdateResourcesParams ¶ms, +- Errors &error) ++bool SandboxerController::Update(sandbox_sandbox *apiSandbox, ++ string_array *fields, Errors &error) + { +- return m_client->UpdateResources(sandboxId, params, error); ++ return m_client->Update(apiSandbox, fields, error); + } + + bool SandboxerController::Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) +diff --git a/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.h b/src/daemon/sandbox/sandboxer/controller/sandboxer_controller.h +similarity index 82% +rename from src/daemon/sandbox/controller/sandboxer/sandboxer_controller.h +rename to src/daemon/sandbox/sandboxer/controller/sandboxer_controller.h +index 8cb7fe7c..13ab86ab 100644 +--- a/src/daemon/sandbox/controller/sandboxer/sandboxer_controller.h ++++ b/src/daemon/sandbox/sandboxer/controller/sandboxer_controller.h +@@ -31,19 +31,12 @@ public: + SandboxerController(const std::string &sandboxer, const std::string &address); + virtual ~SandboxerController(); + bool Init(Errors &error) override; +- void Destroy() override; + bool Create(const std::string &sandboxId, + const ControllerCreateParams ¶ms, + Errors &error) override; + std::unique_ptr Start(const std::string &sandboxId, Errors &error) override; + std::unique_ptr Platform(const std::string &sandboxId, Errors &error) override; +- bool Prepare(containerd::types::Sandbox &apiSandbox, std::vector &fields, +- Errors &error) override; +- bool Purge(containerd::types::Sandbox &apiSandbox, std::vector &fields, +- Errors &error) override; +- bool UpdateResources(const std::string &sandboxId, +- const ControllerUpdateResourcesParams ¶ms, +- Errors &error) override; ++ bool Update(sandbox_sandbox *apiSandbox, string_array *fields, Errors &error) override; + bool Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) override; + bool Wait(std::shared_ptr cb, const std::string &sandboxId, Errors &error) override; + std::unique_ptr Status(const std::string &sandboxId, bool verbose, Errors &error) override; +diff --git a/src/daemon/sandbox/sandboxer/sandboxer_sandbox.cc b/src/daemon/sandbox/sandboxer/sandboxer_sandbox.cc +new file mode 100644 +index 00000000..726b7b3a +--- /dev/null ++++ b/src/daemon/sandbox/sandboxer/sandboxer_sandbox.cc +@@ -0,0 +1,254 @@ ++/****************************************************************************** ++ * 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-11-20 ++ * Description: provide sandboxer sandbox class definition ++ *********************************************************************************/ ++#include "sandboxer_sandbox.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include "utils_file.h" ++#include "utils.h" ++#include "cxxutils.h" ++ ++namespace sandbox { ++ ++SandboxerSandbox::SandboxerSandbox(const std::string id, const std::string &rootdir, const std::string &statedir, const std::string name, ++ const RuntimeInfo info, std::string netMode, std::string netNsPath, const runtime::v1::PodSandboxConfig sandboxConfig, ++ const std::string image):Sandbox(id, rootdir, statedir, name, info, netMode, ++ netNsPath, sandboxConfig, image) ++{ ++} ++ ++auto SandboxerSandbox::GetTasksJsonPath() -> std::string ++{ ++ return GetStateDir() + std::string("/") + SANDBOX_TASKS_JSON; ++} ++ ++auto SandboxerSandbox::AddTaskById(const char *task_id, sandbox_task *task) -> bool ++{ ++ ++ std::string taskId = std::string(task_id); ++ auto iter = m_tasks.find(taskId); ++ ++ if (iter != m_tasks.end()) { ++ ERROR("Failed to add existing sandbox task %s for sandbox: %s", ++ task_id, GetId().c_str()); ++ return false; ++ } ++ m_tasks[taskId] = std::make_shared(task); ++ return true; ++} ++ ++auto SandboxerSandbox::ReadSandboxTasksJson() -> sandbox_tasks * ++{ ++ const std::string path = GetTasksJsonPath(); ++ __isula_auto_free parser_error err = nullptr; ++ sandbox_tasks *tasksArray = nullptr; ++ ++ ReadGuard lock(m_tasksMutex); ++ tasksArray = sandbox_tasks_parse_file(path.c_str(), nullptr, &err); ++ if (tasksArray == nullptr) { ++ WARN("Failed to read %s tasks json: %s", path.c_str(), err); ++ } ++ return tasksArray; ++} ++ ++auto SandboxerSandbox::WriteSandboxTasksJson(std::string &tasks_json) -> bool ++{ ++ int nret = 0; ++ const std::string path = GetTasksJsonPath(); ++ ++ WriteGuard lock(m_tasksMutex); ++ nret = util_atomic_write_file(path.c_str(), tasks_json.c_str(), tasks_json.size(), CONFIG_FILE_MODE, false); ++ if (nret != 0) { ++ SYSERROR("Failed to write file %s", path.c_str()); ++ } ++ return nret == 0; ++} ++ ++auto SandboxerSandbox::DeleteSandboxTasksJson() -> bool ++{ ++ int get_err = 0; ++ const std::string path = GetTasksJsonPath(); ++ ++ WriteGuard lock(m_tasksMutex); ++ if (util_fileself_exists(path.c_str()) && ++ !util_force_remove_file(path.c_str(), &get_err)) { ++ errno = get_err; ++ SYSERROR("Failed to remove file %s", path.c_str()); ++ return false; ++ } ++ ++ return true; ++} ++ ++void SandboxerSandbox::AddSandboxTasksByArray(sandbox_tasks *tasksArray) ++{ ++ size_t i; ++ ++ WriteGuard lock(m_tasksMutex); ++ for (i = 0; i < tasksArray->tasks_len; i++) { ++ if (!AddTaskById(tasksArray->tasks[i]->task_id, tasksArray->tasks[i])) { ++ return; ++ } ++ tasksArray->tasks[i] = nullptr; ++ } ++ tasksArray->tasks_len = 0; ++} ++ ++void SandboxerSandbox::LoadSandboxTasks() ++{ ++ sandbox_tasks *tasksArray = nullptr; ++ ++ tasksArray = ReadSandboxTasksJson(); ++ if (tasksArray == nullptr) { ++ return; ++ } ++ ++ AddSandboxTasksByArray(tasksArray); ++ ++ free_sandbox_tasks(tasksArray); ++} ++ ++auto SandboxerSandbox::SaveSandboxTasks() -> bool ++{ ++ std::string tasks_json; ++ ++ if (m_tasks.empty()) { ++ return DeleteSandboxTasksJson(); ++ } ++ ++ tasks_json = GetAnySandboxTasks(); ++ if (tasks_json.empty()) { ++ ERROR("Failed to get sandbox tasks json for sandbox: '%s'", GetId().c_str()); ++ return false; ++ } ++ ++ return WriteSandboxTasksJson(tasks_json); ++} ++ ++auto SandboxerSandbox::AddSandboxTasks(sandbox_task *task) -> bool ++{ ++ if (task == nullptr) { ++ return true; ++ } ++ if (task->task_id == nullptr) { ++ return false; ++ } ++ ++ WriteGuard lock(m_tasksMutex); ++ ++ return AddTaskById(task->task_id, task); ++} ++ ++auto SandboxerSandbox::GetAnySandboxTasks() -> std::string ++{ ++ __isula_auto_free parser_error err = nullptr; ++ sandbox_tasks tasksArray = { 0 }; ++ size_t i = 0; ++ __isula_auto_free char *tasks_json = nullptr; ++ ++ tasksArray.tasks = (sandbox_task **)util_smart_calloc_s(sizeof(sandbox_task *), m_tasks.size()); ++ if (tasksArray.tasks == nullptr) { ++ SYSERROR("Out of memory."); ++ return std::string(""); ++ } ++ ++ ReadGuard lock(m_tasksMutex); ++ for (auto const& [_, val] : m_tasks) { ++ /* ++ * We ignore that the processes are modified ++ * when we generate tasks json string. ++ * Because no matter whether a process is deleted or added, ++ * the Update of sandbox api will be called eventually. ++ * ++ * And we ignore that the task is freed after we do GetTask(). ++ * Because the only way to free task is DeleteSandboxTasks() ++ * which needs write lock of m_tasksMutex. ++ */ ++ tasksArray.tasks[i] = val->GetTask(); ++ i++; ++ } ++ tasksArray.tasks_len = m_tasks.size(); ++ ++ tasks_json = sandbox_tasks_generate_json(&tasksArray, nullptr, &(err)); ++ if (tasks_json == nullptr || strlen(tasks_json) == 0) { ++ ERROR("Failed to get sandbox tasks json for sandbox: '%s'", GetId().c_str()); ++ free(tasksArray.tasks); ++ return std::string(""); ++ } ++ ++ free(tasksArray.tasks); ++ return std::string(tasks_json); ++} ++ ++void SandboxerSandbox::DeleteSandboxTasks(const char *containerId) ++{ ++ if (containerId == nullptr) { ++ return; ++ } ++ ++ std::string taskId = std::string(containerId); ++ ++ WriteGuard lock(m_tasksMutex); ++ auto iter = m_tasks.find(taskId); ++ if (iter == m_tasks.end()) { ++ return; ++ } ++ m_tasks.erase(iter); ++} ++ ++auto SandboxerSandbox::AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool ++{ ++ if (containerId == nullptr || processes == nullptr) { ++ ERROR("Empty args."); ++ return false; ++ } ++ ++ std::string taskId = std::string(containerId); ++ ++ ReadGuard lock(m_tasksMutex); ++ auto iter = m_tasks.find(taskId); ++ if (iter == m_tasks.end()) { ++ SYSERROR("Failed to find container %s", containerId); ++ return false; ++ } ++ ++ return iter->second->AddSandboxTasksProcess(processes); ++} ++ ++void SandboxerSandbox::DeleteSandboxTasksProcess(const char *containerId, const char *execId) ++{ ++ if (containerId == nullptr || execId == nullptr) { ++ return; ++ } ++ ++ std::string taskId = std::string(containerId); ++ ++ ReadGuard lock(m_tasksMutex); ++ auto iter = m_tasks.find(taskId); ++ if (iter == m_tasks.end()) { ++ return; ++ } ++ iter->second->DeleteSandboxTasksProcess(execId); ++} ++ ++} +\ No newline at end of file +diff --git a/src/daemon/sandbox/sandboxer/sandboxer_sandbox.h b/src/daemon/sandbox/sandboxer/sandboxer_sandbox.h +new file mode 100644 +index 00000000..552eb328 +--- /dev/null ++++ b/src/daemon/sandbox/sandboxer/sandboxer_sandbox.h +@@ -0,0 +1,63 @@ ++/****************************************************************************** ++ * 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-11-20 ++ * Description: provide sandboxer sandbox class definition ++ *********************************************************************************/ ++ ++#ifndef DAEMON_SANDBOX_SANDBOXER_SANDBOX_H ++#define DAEMON_SANDBOX_SANDBOXER_SANDBOX_H ++ ++#include ++#include ++#include ++ ++#include "read_write_lock.h" ++#include "sandbox_task.h" ++#include "sandbox.h" ++ ++namespace sandbox { ++ ++class SandboxerSandbox : public Sandbox { ++public: ++ SandboxerSandbox(const std::string id, const std::string &rootdir, const std::string &statedir, const std::string name = "", ++ const RuntimeInfo info = {"", "", ""}, std::string netMode = DEFAULT_NETMODE, std::string netNsPath = "", ++ const runtime::v1::PodSandboxConfig sandboxConfig = runtime::v1::PodSandboxConfig::default_instance(), ++ const std::string image = ""); ++ virtual ~SandboxerSandbox() = default; ++ ++ // for sandbox api update ++ auto GetTasksJsonPath() -> std::string; ++ void LoadSandboxTasks() override; ++ auto SaveSandboxTasks() -> bool override; ++ auto AddSandboxTasks(sandbox_task *task) -> bool override; ++ auto GetAnySandboxTasks() -> std::string override; ++ void DeleteSandboxTasks(const char *containerId) override; ++ auto AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool override; ++ void DeleteSandboxTasksProcess(const char *containerId, const char *execId) override; ++ ++private: ++ auto AddTaskById(const char *task_id, sandbox_task *task) -> bool; ++ auto ReadSandboxTasksJson() -> sandbox_tasks *; ++ auto WriteSandboxTasksJson(std::string &tasks_json) -> bool; ++ auto DeleteSandboxTasksJson() -> bool; ++ void AddSandboxTasksByArray(sandbox_tasks *tasksArray); ++ ++private: ++ // use m_tasksMutex to ensure the correctness of the tasks ++ RWMutex m_tasksMutex; ++ // for sandbox api update, containerId --> tasks ++ std::map> m_tasks; ++}; ++ ++} // namespace sandbox ++ ++#endif // DAEMON_SANDBOX_SANDBOXER_SANDBOX_H +\ No newline at end of file +diff --git a/src/daemon/sandbox/shim/CMakeLists.txt b/src/daemon/sandbox/shim/CMakeLists.txt +new file mode 100755 +index 00000000..66fff738 +--- /dev/null ++++ b/src/daemon/sandbox/shim/CMakeLists.txt +@@ -0,0 +1,15 @@ ++# get current directory sources files ++aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} shim_sandbox_srcs) ++ ++add_subdirectory(controller) ++ ++set(SHIM_SANDBOX_SRCS ++ ${shim_sandbox_srcs} ++ ${CONTROLLER_SHIM_SRCS} ++ PARENT_SCOPE ++ ) ++set(SHIM_SANDBOX_INCS ++ ${CMAKE_CURRENT_SOURCE_DIR} ++ ${CONTROLLER_SHIM_INCS} ++ PARENT_SCOPE ++ ) +diff --git a/src/daemon/sandbox/controller/shim/CMakeLists.txt b/src/daemon/sandbox/shim/controller/CMakeLists.txt +similarity index 100% +rename from src/daemon/sandbox/controller/shim/CMakeLists.txt +rename to src/daemon/sandbox/shim/controller/CMakeLists.txt +diff --git a/src/daemon/sandbox/controller/shim/shim_controller.cc b/src/daemon/sandbox/shim/controller/shim_controller.cc +similarity index 97% +rename from src/daemon/sandbox/controller/shim/shim_controller.cc +rename to src/daemon/sandbox/shim/controller/shim_controller.cc +index 14c99168..7e4338f6 100644 +--- a/src/daemon/sandbox/controller/shim/shim_controller.cc ++++ b/src/daemon/sandbox/shim/controller/shim_controller.cc +@@ -45,8 +45,6 @@ bool ShimController::Init(Errors &error) + return true; + } + +-void ShimController::Destroy() {} +- + void ShimController::ApplySandboxLinuxOptions(const runtime::v1::LinuxPodSandboxConfig &lc, host_config *hc, + container_config *custom_config, Errors &error) + { +@@ -340,21 +338,8 @@ std::unique_ptr ShimController::Platform(const std::stri + return nullptr; + } + +-bool ShimController::Prepare(containerd::types::Sandbox &apiSandbox, +- std::vector &fields, Errors &error) +-{ +- return true; +-} +- +-bool ShimController::Purge(containerd::types::Sandbox &apiSandbox, +- std::vector &fields, Errors &error) +-{ +- return true; +-} +- +-bool ShimController::UpdateResources(const std::string &sandboxId, +- const ControllerUpdateResourcesParams ¶ms, +- Errors &error) ++bool ShimController::Update(sandbox_sandbox *apiSandbox, ++ string_array *fields, Errors &error) + { + return true; + } +diff --git a/src/daemon/sandbox/controller/shim/shim_controller.h b/src/daemon/sandbox/shim/controller/shim_controller.h +similarity index 89% +rename from src/daemon/sandbox/controller/shim/shim_controller.h +rename to src/daemon/sandbox/shim/controller/shim_controller.h +index 1985ddc0..fc86be98 100644 +--- a/src/daemon/sandbox/controller/shim/shim_controller.h ++++ b/src/daemon/sandbox/shim/controller/shim_controller.h +@@ -32,26 +32,18 @@ + + namespace sandbox { + +-const std::string SHIM_CONTROLLER_NAME = "shim"; +- + class ShimController : public Controller { + public: + ShimController(const std::string &sandboxer); + virtual ~ShimController(); + bool Init(Errors &error) override; +- void Destroy() override; + bool Create(const std::string &sandboxId, + const ControllerCreateParams ¶ms, + Errors &error) override; + std::unique_ptr Start(const std::string &sandboxId, Errors &error) override; + std::unique_ptr Platform(const std::string &sandboxId, Errors &error) override; +- bool Prepare(containerd::types::Sandbox &apiSandbox, std::vector &fields, +- Errors &error) override; +- bool Purge(containerd::types::Sandbox &apiSandbox, std::vector &fields, +- Errors &error) override; +- bool UpdateResources(const std::string &sandboxId, +- const ControllerUpdateResourcesParams ¶ms, +- Errors &error) override; ++ bool Update(sandbox_sandbox *apiSandbox, ++ string_array *fields, Errors &error) override; + bool Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) override; + bool Wait(std::shared_ptr cb, const std::string &sandboxId, Errors &error) override; + std::unique_ptr Status(const std::string &sandboxId, bool verbose, Errors &error) override; +diff --git a/src/daemon/sandbox/shim/shim_sandbox.cc b/src/daemon/sandbox/shim/shim_sandbox.cc +new file mode 100644 +index 00000000..2efb8d7c +--- /dev/null ++++ b/src/daemon/sandbox/shim/shim_sandbox.cc +@@ -0,0 +1,65 @@ ++/****************************************************************************** ++ * 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-11-20 ++ * Description: provide sandboxer sandbox class definition ++ *********************************************************************************/ ++#include "shim_sandbox.h" ++ ++#include ++#include ++ ++#include ++#include ++ ++ ++namespace sandbox { ++ ++ShimSandbox::ShimSandbox(const std::string id, const std::string &rootdir, const std::string &statedir, const std::string name, ++ const RuntimeInfo info, std::string netMode, std::string netNsPath, const runtime::v1::PodSandboxConfig sandboxConfig, ++ const std::string image):Sandbox(id, rootdir, statedir, name, info, netMode, ++ netNsPath, sandboxConfig, image) ++{ ++} ++ ++void ShimSandbox::LoadSandboxTasks() ++{ ++} ++ ++auto ShimSandbox::SaveSandboxTasks() -> bool ++{ ++ return true; ++} ++ ++auto ShimSandbox::AddSandboxTasks(sandbox_task *task) -> bool ++{ ++ return true; ++} ++ ++auto ShimSandbox::GetAnySandboxTasks() -> std::string ++{ ++ return std::string("Nothing for shim."); ++} ++ ++void ShimSandbox::DeleteSandboxTasks(const char *containerId) ++{ ++} ++ ++auto ShimSandbox::AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool ++{ ++ return true; ++} ++ ++void ShimSandbox::DeleteSandboxTasksProcess(const char *containerId, const char *execId) ++{ ++} ++ ++} +\ No newline at end of file +diff --git a/src/daemon/sandbox/shim/shim_sandbox.h b/src/daemon/sandbox/shim/shim_sandbox.h +new file mode 100644 +index 00000000..82da0573 +--- /dev/null ++++ b/src/daemon/sandbox/shim/shim_sandbox.h +@@ -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-11-20 ++ * Description: provide shim sandbox class definition ++ *********************************************************************************/ ++ ++#ifndef DAEMON_SANDBOX_SHIM_SANDBOX_H ++#define DAEMON_SANDBOX_SHIM_SANDBOX_H ++ ++#include ++#include ++#include ++ ++#include "read_write_lock.h" ++#include "sandbox_task.h" ++#include "sandbox.h" ++ ++namespace sandbox { ++ ++class ShimSandbox : public Sandbox { ++public: ++ ShimSandbox(const std::string id, const std::string &rootdir, const std::string &statedir, const std::string name = "", ++ const RuntimeInfo info = {"", "", ""}, std::string netMode = DEFAULT_NETMODE, std::string netNsPath = "", ++ const runtime::v1::PodSandboxConfig sandboxConfig = runtime::v1::PodSandboxConfig::default_instance(), ++ const std::string image = ""); ++ virtual ~ShimSandbox() = default; ++ ++ // for sandbox api update ++ void LoadSandboxTasks() override; ++ auto SaveSandboxTasks() -> bool override; ++ auto AddSandboxTasks(sandbox_task *task) -> bool override; ++ auto GetAnySandboxTasks() -> std::string override; ++ void DeleteSandboxTasks(const char *containerId) override; ++ auto AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool override; ++ void DeleteSandboxTasksProcess(const char *containerId, const char *execId) override; ++}; ++ ++} // namespace sandbox ++ ++#endif // DAEMON_SANDBOX_SHIM_SANDBOX_H +\ No newline at end of file +-- +2.34.1 + diff --git a/0154-add-linux-capability.h-head-file.patch b/0154-add-linux-capability.h-head-file.patch new file mode 100644 index 0000000000000000000000000000000000000000..24853ac6dcd14d7468a43e9c248d0cdbc88c6980 --- /dev/null +++ b/0154-add-linux-capability.h-head-file.patch @@ -0,0 +1,25 @@ +From 94cf20fe53c0a42f703dd6a0122c619c0ee06715 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Sat, 23 Nov 2024 03:45:22 +1400 +Subject: [PATCH 154/156] add linux/capability.h head file + +Signed-off-by: zhongtao +--- + src/utils/cutils/utils_cap.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/utils/cutils/utils_cap.h b/src/utils/cutils/utils_cap.h +index c7e78ac2..e741b565 100644 +--- a/src/utils/cutils/utils_cap.h ++++ b/src/utils/cutils/utils_cap.h +@@ -18,6 +18,7 @@ + + #include + #include ++#include + + #ifdef __cplusplus + extern "C" { +-- +2.34.1 + diff --git a/0155-sandbox-fix-unused-variables.patch b/0155-sandbox-fix-unused-variables.patch new file mode 100644 index 0000000000000000000000000000000000000000..5dbc54c9d1f59c5cf9cc5747b1748abec1b18726 --- /dev/null +++ b/0155-sandbox-fix-unused-variables.patch @@ -0,0 +1,34 @@ +From baa25031fcf68443bc1262bebec69a54fed38d88 Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Mon, 25 Nov 2024 15:18:13 +0800 +Subject: [PATCH 155/156] sandbox:fix unused variables + +Signed-off-by: liuxu +--- + .../sandboxer/controller/client/grpc_sandboxer_client.cc | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.cc b/src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.cc +index d7ff76d7..5b7f3c1c 100644 +--- a/src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.cc ++++ b/src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.cc +@@ -92,7 +92,6 @@ auto SandboxerClient::InitCreateRequest(sandbox_create_request &request, + (void)memcpy(request.options->value, encoded.c_str(), encoded.size()); + request.options->value_len = encoded.size(); + request.netns_path = util_strdup_s(params.netNSPath.c_str()); +- sandbox_mount **mounts = NULL; + size_t mounts_len = params.mounts.size(); + if (mounts_len > 0) { + request.rootfs = (sandbox_mount**)util_common_calloc_s(mounts_len * sizeof(sandbox_mount *)); +@@ -112,7 +111,7 @@ auto SandboxerClient::InitCreateRequest(sandbox_create_request &request, + free(m); + return false; + } +- mounts[request.rootfs_len++] = m; ++ request.rootfs[request.rootfs_len++] = m; + m = NULL; + } + } +-- +2.34.1 + diff --git a/0156-sandbox-sandbox-api-adapt-rust-interface-UT.patch b/0156-sandbox-sandbox-api-adapt-rust-interface-UT.patch new file mode 100644 index 0000000000000000000000000000000000000000..410fb2d728a47f97ee045e4a261b7a1f151cf3a9 --- /dev/null +++ b/0156-sandbox-sandbox-api-adapt-rust-interface-UT.patch @@ -0,0 +1,3021 @@ +From 6de0c825b7d8dd2d7b1c53524f6ecebcef22bc75 Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Fri, 22 Nov 2024 14:11:42 +0800 +Subject: [PATCH 156/156] sandbox: sandbox api adapt rust interface UT + +Signed-off-by: liuxu +--- + test/cutils/utils_transform/CMakeLists.txt | 1 - + test/mocks/controller_stub_mock.cc | 314 ---------------- + test/mocks/controller_stub_mock.h | 239 ------------ + test/mocks/grpc_async_wait_call_mock.cc | 92 ----- + test/mocks/grpc_async_wait_call_mock.h | 37 -- + test/mocks/grpc_sandboxer_client_mock.cc | 44 +-- + test/mocks/grpc_sandboxer_client_mock.h | 11 +- + test/mocks/grpc_sandboxer_monitor_mock.cc | 51 --- + test/mocks/rust_sandbox_api_mock.cc | 103 ++++++ + test/mocks/rust_sandbox_api_mock.h | 39 ++ + test/mocks/sandbox_manager_mock.cc | 42 +++ + ..._monitor_mock.h => sandbox_manager_mock.h} | 35 +- + test/mocks/sandboxer_controller_mock.cc | 116 ++++++ + test/mocks/sandboxer_controller_mock.h | 52 +++ + test/mocks/sandboxer_sandbox_mock.cc | 72 ++++ + test/mocks/sandboxer_sandbox_mock.h | 43 +++ + test/mocks/shim_controller_mock.cc | 36 +- + test/mocks/shim_controller_mock.h | 11 +- + test/mocks/shim_sandbox_mock.cc | 72 ++++ + test/mocks/shim_sandbox_mock.h | 43 +++ + test/sandbox/controller/CMakeLists.txt | 2 - + test/sandbox/controller/controller_common.cc | 51 ++- + test/sandbox/controller/controller_common.h | 9 +- + .../sandbox/controller/manager/CMakeLists.txt | 15 +- + .../controller/sandboxer/CMakeLists.txt | 1 - + .../sandboxer/async_wait_call/CMakeLists.txt | 37 -- + .../async_wait_call/async_wait_call_ut.cc | 115 ------ + .../async_wait_call/dummy_monitor_utils.h | 121 ------ + .../sandboxer/sandboxer_client/CMakeLists.txt | 22 +- + .../sandboxer_client/sandboxer_client_ut.cc | 344 ++++++++---------- + .../sandboxer_controller/CMakeLists.txt | 11 +- + .../sandboxer_controller_ut.cc | 62 +--- + test/sandbox/controller/shim/CMakeLists.txt | 7 +- + test/sandbox/sandbox/CMakeLists.txt | 21 +- + test/sandbox/sandbox/sandbox_ut.cc | 5 +- + test/sandbox/sandbox_manager/CMakeLists.txt | 21 +- + 36 files changed, 861 insertions(+), 1436 deletions(-) + delete mode 100644 test/mocks/controller_stub_mock.cc + delete mode 100644 test/mocks/controller_stub_mock.h + delete mode 100644 test/mocks/grpc_async_wait_call_mock.cc + delete mode 100644 test/mocks/grpc_async_wait_call_mock.h + delete mode 100644 test/mocks/grpc_sandboxer_monitor_mock.cc + create mode 100644 test/mocks/rust_sandbox_api_mock.cc + create mode 100644 test/mocks/rust_sandbox_api_mock.h + create mode 100644 test/mocks/sandbox_manager_mock.cc + rename test/mocks/{grpc_sandboxer_monitor_mock.h => sandbox_manager_mock.h} (55%) + create mode 100644 test/mocks/sandboxer_controller_mock.cc + create mode 100644 test/mocks/sandboxer_controller_mock.h + create mode 100644 test/mocks/sandboxer_sandbox_mock.cc + create mode 100644 test/mocks/sandboxer_sandbox_mock.h + create mode 100644 test/mocks/shim_sandbox_mock.cc + create mode 100644 test/mocks/shim_sandbox_mock.h + delete mode 100644 test/sandbox/controller/sandboxer/async_wait_call/CMakeLists.txt + delete mode 100644 test/sandbox/controller/sandboxer/async_wait_call/async_wait_call_ut.cc + delete mode 100644 test/sandbox/controller/sandboxer/async_wait_call/dummy_monitor_utils.h + +diff --git a/test/cutils/utils_transform/CMakeLists.txt b/test/cutils/utils_transform/CMakeLists.txt +index fde9c9f9..23c870fa 100644 +--- a/test/cutils/utils_transform/CMakeLists.txt ++++ b/test/cutils/utils_transform/CMakeLists.txt +@@ -15,7 +15,6 @@ target_include_directories(${EXE} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/map + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cpputils +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/google/protobuf + ) + target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${ISULA_LIBUTILS_LIBRARY} libutils_ut -lcrypto -lprotobuf -lyajl -lz) + add_test(NAME ${EXE} COMMAND ${EXE} --gtest_output=xml:${EXE}-Results.xml) +diff --git a/test/mocks/controller_stub_mock.cc b/test/mocks/controller_stub_mock.cc +deleted file mode 100644 +index 712540bb..00000000 +--- a/test/mocks/controller_stub_mock.cc ++++ /dev/null +@@ -1,314 +0,0 @@ +-#include "controller_stub_mock.h" +- +-static std::shared_ptr g_controller_stub_mock = NULL; +- +-std::unique_ptr NewDummyControllerStub() +-{ +- std::unique_ptr stub(new DummyControllerStub()); +- return stub; +-} +- +-void MockControllerStub_SetMock(std::shared_ptr mock) +-{ +- g_controller_stub_mock = mock; +-} +- +-::grpc::Status DummyControllerStub::Create(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerCreateRequest &request, +- ::containerd::services::sandbox::v1::ControllerCreateResponse* response) +-{ +- if (g_controller_stub_mock == NULL) { +- return ::grpc::Status::OK; +- } +- return g_controller_stub_mock->Create(context, request, response); +-} +- +-::grpc::Status DummyControllerStub::Start(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStartRequest &request, +- ::containerd::services::sandbox::v1::ControllerStartResponse* response) +-{ +- if (g_controller_stub_mock == NULL) { +- return ::grpc::Status::OK; +- } +- return g_controller_stub_mock->Start(context, request, response); +-} +- +-::grpc::Status DummyControllerStub::Platform(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerPlatformRequest &request, +- ::containerd::services::sandbox::v1::ControllerPlatformResponse* response) +-{ +- if (g_controller_stub_mock == NULL) { +- return ::grpc::Status::OK; +- } +- return g_controller_stub_mock->Platform(context, request, response); +-} +- +-::grpc::Status DummyControllerStub::Prepare(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::PrepareRequest &request, +- ::containerd::services::sandbox::v1::PrepareResponse* response) +-{ +- if (g_controller_stub_mock == NULL) { +- return ::grpc::Status::OK; +- } +- return g_controller_stub_mock->Prepare(context, request, response); +-} +- +-::grpc::Status DummyControllerStub::Purge(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::PurgeRequest &request, +- ::containerd::services::sandbox::v1::PurgeResponse* response) +-{ +- if (g_controller_stub_mock == NULL) { +- return ::grpc::Status::OK; +- } +- return g_controller_stub_mock->Purge(context, request, response); +-} +- +-::grpc::Status DummyControllerStub::UpdateResources(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::UpdateResourcesRequest &request, +- ::containerd::services::sandbox::v1::UpdateResourcesResponse* response) +-{ +- if (g_controller_stub_mock == NULL) { +- return ::grpc::Status::OK; +- } +- return g_controller_stub_mock->UpdateResources(context, request, response); +-} +- +-::grpc::Status DummyControllerStub::Stop(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStopRequest &request, +- ::containerd::services::sandbox::v1::ControllerStopResponse* response) +-{ +- if (g_controller_stub_mock == NULL) { +- return ::grpc::Status::OK; +- } +- return g_controller_stub_mock->Stop(context, request, response); +-} +- +-::grpc::Status DummyControllerStub::Wait(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerWaitRequest &request, +- ::containerd::services::sandbox::v1::ControllerWaitResponse* response) +-{ +- if (g_controller_stub_mock == NULL) { +- return ::grpc::Status::OK; +- } +- return g_controller_stub_mock->Wait(context, request, response); +-} +- +-::grpc::Status DummyControllerStub::Status(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStatusRequest &request, +- ::containerd::services::sandbox::v1::ControllerStatusResponse* response) +-{ +- if (g_controller_stub_mock == NULL) { +- return ::grpc::Status::OK; +- } +- return g_controller_stub_mock->Status(context, request, response); +-} +- +-::grpc::Status DummyControllerStub::Shutdown(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerShutdownRequest &request, +- ::containerd::services::sandbox::v1::ControllerShutdownResponse* response) +-{ +- if (g_controller_stub_mock == NULL) { +- return ::grpc::Status::OK; +- } +- return g_controller_stub_mock->Shutdown(context, request, response); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerCreateResponse>* +-DummyControllerStub::AsyncCreateRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerCreateRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->AsyncCreateRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerCreateResponse>* +-DummyControllerStub::PrepareAsyncCreateRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerCreateRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->PrepareAsyncCreateRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStartResponse>* +-DummyControllerStub::AsyncStartRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStartRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->AsyncStartRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStartResponse>* +-DummyControllerStub::PrepareAsyncStartRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStartRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->PrepareAsyncStartRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerPlatformResponse>* +-DummyControllerStub::AsyncPlatformRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerPlatformRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->AsyncPlatformRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerPlatformResponse>* +-DummyControllerStub::PrepareAsyncPlatformRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerPlatformRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->PrepareAsyncPlatformRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::PrepareResponse>* +-DummyControllerStub::AsyncPrepareRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::PrepareRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->AsyncPrepareRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::PrepareResponse>* +-DummyControllerStub::PrepareAsyncPrepareRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::PrepareRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->PrepareAsyncPrepareRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::PurgeResponse>* +-DummyControllerStub::AsyncPurgeRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::PurgeRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->AsyncPurgeRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::PurgeResponse>* +-DummyControllerStub::PrepareAsyncPurgeRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::PurgeRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->PrepareAsyncPurgeRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::UpdateResourcesResponse>* +-DummyControllerStub::AsyncUpdateResourcesRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::UpdateResourcesRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->AsyncUpdateResourcesRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::UpdateResourcesResponse>* +-DummyControllerStub::PrepareAsyncUpdateResourcesRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::UpdateResourcesRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->PrepareAsyncUpdateResourcesRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStopResponse>* +-DummyControllerStub::AsyncStopRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStopRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->AsyncStopRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStopResponse>* +-DummyControllerStub::PrepareAsyncStopRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStopRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->PrepareAsyncStopRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerWaitResponse>* +-DummyControllerStub::AsyncWaitRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerWaitRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->AsyncWaitRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerWaitResponse>* +-DummyControllerStub::PrepareAsyncWaitRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerWaitRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->PrepareAsyncWaitRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStatusResponse>* +-DummyControllerStub::AsyncStatusRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStatusRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->AsyncStatusRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStatusResponse>* +-DummyControllerStub::PrepareAsyncStatusRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStatusRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->PrepareAsyncStatusRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerShutdownResponse>* +-DummyControllerStub::AsyncShutdownRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerShutdownRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->AsyncShutdownRaw(context, request, cq); +-} +- +-::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerShutdownResponse>* +-DummyControllerStub::PrepareAsyncShutdownRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerShutdownRequest &request, ::grpc::CompletionQueue* cq) +-{ +- if (g_controller_stub_mock == NULL) { +- return NULL; +- } +- return g_controller_stub_mock->PrepareAsyncShutdownRaw(context, request, cq); +-} +diff --git a/test/mocks/controller_stub_mock.h b/test/mocks/controller_stub_mock.h +deleted file mode 100644 +index 85cb82bb..00000000 +--- a/test/mocks/controller_stub_mock.h ++++ /dev/null +@@ -1,239 +0,0 @@ +-/****************************************************************************** +- * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: xuxuepeng +- * Create: 2023-07-15 +- * Description: provide grpc controller stub mock +- ******************************************************************************/ +- +-#ifndef _ISULAD_TEST_MOCKS_CONTROLLER_STUB_MOCK_H +-#define _ISULAD_TEST_MOCKS_CONTROLLER_STUB_MOCK_H +- +- +-#include +-#include "sandbox.grpc.pb.h" +- +-// MockControllerStub is a mock implementation of the Controller::StubInterface interface. +-class MockControllerStub { +-public: +- MOCK_METHOD3(Create, ::grpc::Status(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerCreateRequest &request, +- ::containerd::services::sandbox::v1::ControllerCreateResponse* response)); +- MOCK_METHOD3(Start, ::grpc::Status(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStartRequest &request, +- ::containerd::services::sandbox::v1::ControllerStartResponse* response)); +- MOCK_METHOD3(Platform, ::grpc::Status(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerPlatformRequest &request, +- ::containerd::services::sandbox::v1::ControllerPlatformResponse* response)); +- MOCK_METHOD3(Prepare, ::grpc::Status(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::PrepareRequest &request, +- ::containerd::services::sandbox::v1::PrepareResponse* response)); +- MOCK_METHOD3(Purge, ::grpc::Status(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::PurgeRequest &request, +- ::containerd::services::sandbox::v1::PurgeResponse* response)); +- MOCK_METHOD3(UpdateResources, ::grpc::Status(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::UpdateResourcesRequest &request, +- ::containerd::services::sandbox::v1::UpdateResourcesResponse* response)); +- MOCK_METHOD3(Stop, ::grpc::Status(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStopRequest &request, +- ::containerd::services::sandbox::v1::ControllerStopResponse* response)); +- MOCK_METHOD3(Wait, ::grpc::Status(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerWaitRequest &request, +- ::containerd::services::sandbox::v1::ControllerWaitResponse* response)); +- MOCK_METHOD3(Status, ::grpc::Status(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStatusRequest &request, +- ::containerd::services::sandbox::v1::ControllerStatusResponse* response)); +- MOCK_METHOD3(Shutdown, ::grpc::Status(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerShutdownRequest &request, +- ::containerd::services::sandbox::v1::ControllerShutdownResponse* response)); +- MOCK_METHOD3(AsyncCreateRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerCreateResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerCreateRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(PrepareAsyncCreateRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerCreateResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerCreateRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(AsyncStartRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStartResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerStartRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(PrepareAsyncStartRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStartResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerStartRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(AsyncPlatformRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerPlatformResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerPlatformRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(PrepareAsyncPlatformRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerPlatformResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerPlatformRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(AsyncPrepareRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::PrepareResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::PrepareRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(PrepareAsyncPrepareRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::PrepareResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::PrepareRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(AsyncPurgeRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::PurgeResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::PurgeRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(PrepareAsyncPurgeRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::PurgeResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::PurgeRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(AsyncUpdateResourcesRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::UpdateResourcesResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::UpdateResourcesRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(PrepareAsyncUpdateResourcesRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::UpdateResourcesResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::UpdateResourcesRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(AsyncStopRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStopResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerStopRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(PrepareAsyncStopRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStopResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerStopRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(AsyncWaitRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerWaitResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerWaitRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(PrepareAsyncWaitRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerWaitResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerWaitRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(AsyncStatusRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStatusResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerStatusRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(PrepareAsyncStatusRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStatusResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerStatusRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(AsyncShutdownRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerShutdownResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerShutdownRequest &request, +- ::grpc::CompletionQueue* cq)); +- MOCK_METHOD3(PrepareAsyncShutdownRaw, +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerShutdownResponse>* +- (::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerShutdownRequest &request, +- ::grpc::CompletionQueue* cq)); +-}; +- +-class DummyControllerStub: public containerd::services::sandbox::v1::Controller::StubInterface { +-public: +- DummyControllerStub() = default; +- ~DummyControllerStub() = default; +- ::grpc::Status Create(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerCreateRequest &request, +- ::containerd::services::sandbox::v1::ControllerCreateResponse* response) override; +- ::grpc::Status Start(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStartRequest &request, +- ::containerd::services::sandbox::v1::ControllerStartResponse* response) override; +- ::grpc::Status Platform(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerPlatformRequest &request, +- ::containerd::services::sandbox::v1::ControllerPlatformResponse* response) override; +- ::grpc::Status Prepare(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::PrepareRequest &request, +- ::containerd::services::sandbox::v1::PrepareResponse* response) override; +- ::grpc::Status Purge(::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::PurgeRequest &request, +- ::containerd::services::sandbox::v1::PurgeResponse* response) override; +- ::grpc::Status UpdateResources(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::UpdateResourcesRequest &request, +- ::containerd::services::sandbox::v1::UpdateResourcesResponse* response) override; +- ::grpc::Status Stop(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStopRequest &request, +- ::containerd::services::sandbox::v1::ControllerStopResponse* response) override; +- ::grpc::Status Wait(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerWaitRequest &request, +- ::containerd::services::sandbox::v1::ControllerWaitResponse* response) override; +- ::grpc::Status Status(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStatusRequest &request, +- ::containerd::services::sandbox::v1::ControllerStatusResponse* response) override; +- ::grpc::Status Shutdown(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerShutdownRequest &request, +- ::containerd::services::sandbox::v1::ControllerShutdownResponse* response) override; +-private: +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerCreateResponse>* +- AsyncCreateRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerCreateRequest &request, ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerCreateResponse>* +- PrepareAsyncCreateRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerCreateRequest &request, ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStartResponse>* +- AsyncStartRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStartRequest &request, ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStartResponse>* +- PrepareAsyncStartRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStartRequest &request, ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerPlatformResponse>* +- AsyncPlatformRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerPlatformRequest &request, ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerPlatformResponse>* +- PrepareAsyncPlatformRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerPlatformRequest &request, ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::PrepareResponse>* AsyncPrepareRaw( +- ::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::PrepareRequest &request, +- ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::PrepareResponse>* +- PrepareAsyncPrepareRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::PrepareRequest &request, ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::PurgeResponse>* AsyncPurgeRaw( +- ::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::PurgeRequest &request, +- ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::PurgeResponse>* PrepareAsyncPurgeRaw( +- ::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::PurgeRequest &request, +- ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::UpdateResourcesResponse>* +- AsyncUpdateResourcesRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::UpdateResourcesRequest &request, ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::UpdateResourcesResponse>* +- PrepareAsyncUpdateResourcesRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::UpdateResourcesRequest &request, ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStopResponse>* AsyncStopRaw( +- ::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerStopRequest &request, +- ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStopResponse>* +- PrepareAsyncStopRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStopRequest &request, ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerWaitResponse>* AsyncWaitRaw( +- ::grpc::ClientContext* context, const ::containerd::services::sandbox::v1::ControllerWaitRequest &request, +- ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerWaitResponse>* +- PrepareAsyncWaitRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerWaitRequest &request, ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStatusResponse>* +- AsyncStatusRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStatusRequest &request, ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerStatusResponse>* +- PrepareAsyncStatusRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerStatusRequest &request, ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerShutdownResponse>* +- AsyncShutdownRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerShutdownRequest &request, ::grpc::CompletionQueue* cq) override; +- ::grpc::ClientAsyncResponseReaderInterface< ::containerd::services::sandbox::v1::ControllerShutdownResponse>* +- PrepareAsyncShutdownRaw(::grpc::ClientContext* context, +- const ::containerd::services::sandbox::v1::ControllerShutdownRequest &request, ::grpc::CompletionQueue* cq) override; +-}; +- +-std::unique_ptr NewDummyControllerStub(); +- +-void MockControllerStub_SetMock(std::shared_ptr stub); +- +- +-#endif // _ISULAD_TEST_MOCKS_CONTROLLER_STUB_MOCK_H +\ No newline at end of file +diff --git a/test/mocks/grpc_async_wait_call_mock.cc b/test/mocks/grpc_async_wait_call_mock.cc +deleted file mode 100644 +index 5eef1794..00000000 +--- a/test/mocks/grpc_async_wait_call_mock.cc ++++ /dev/null +@@ -1,92 +0,0 @@ +-/****************************************************************************** +- * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: xuxuepeng +- * Create: 2023-07-31 +- * Description: provide grpc sandboxer async wait call mock +- ******************************************************************************/ +- +-#include "grpc_async_wait_call_mock.h" +- +-static std::shared_ptr g_sandboxer_async_wait_call_mock = NULL; +- +-void MockSandboxerAsyncWaitCall_SetMock(std::shared_ptr mock) +-{ +- g_sandboxer_async_wait_call_mock = mock; +-} +- +-SandboxerAsyncWaitCall::SandboxerAsyncWaitCall(std::shared_ptr cb, +- const std::string &sandboxId, const std::string &sandboxer) +-{ +- m_cb = cb; +- m_sandboxId = sandboxId; +- m_sandboxer = sandboxer; +- m_status = grpc::Status::OK; +- m_retryTimes = 0; +- m_retryCounter = 0; +- m_remove = false; +-} +- +-auto SandboxerAsyncWaitCall::Call(containerd::services::sandbox::v1::Controller::StubInterface &stub, +- grpc::CompletionQueue &cq) -> bool +-{ +- if (g_sandboxer_async_wait_call_mock == NULL) { +- return true; +- } +- return g_sandboxer_async_wait_call_mock->Call(stub, cq); +-} +- +-auto SandboxerAsyncWaitCall::HandleResponse() -> SandboxerAsyncWaitStatus +-{ +- if (g_sandboxer_async_wait_call_mock == NULL) { +- return SANDBOXER_ASYNC_WAIT_STATUS_OK; +- } +- return g_sandboxer_async_wait_call_mock->HandleResponse(); +-} +- +-auto SandboxerAsyncWaitCall::Timeout() -> bool +-{ +- if (g_sandboxer_async_wait_call_mock == NULL) { +- return true; +- } +- return g_sandboxer_async_wait_call_mock->Timeout(); +-} +- +-void SandboxerAsyncWaitCall::SandboxExitCallback(bool statusOK, const ControllerExitInfo &exitInfo) +-{ +- if (g_sandboxer_async_wait_call_mock == NULL) { +- return; +- } +- return g_sandboxer_async_wait_call_mock->SandboxExitCallback(statusOK, exitInfo); +-} +- +-void SandboxerAsyncWaitCall::SandboxPendingCallback() +-{ +- if (g_sandboxer_async_wait_call_mock == NULL) { +- return; +- } +- return g_sandboxer_async_wait_call_mock->SandboxPendingCallback(); +-} +- +-void SandboxerAsyncWaitCall::SandboxReadyCallback() +-{ +- if (g_sandboxer_async_wait_call_mock == NULL) { +- return; +- } +- return g_sandboxer_async_wait_call_mock->SandboxReadyCallback(); +-} +- +-auto SandboxerAsyncWaitCall::GetSandboxId() -> const std::string & +-{ +- if (g_sandboxer_async_wait_call_mock == NULL) { +- return m_sandboxId; +- } +- return g_sandboxer_async_wait_call_mock->GetSandboxId(); +-} +diff --git a/test/mocks/grpc_async_wait_call_mock.h b/test/mocks/grpc_async_wait_call_mock.h +deleted file mode 100644 +index c79f998e..00000000 +--- a/test/mocks/grpc_async_wait_call_mock.h ++++ /dev/null +@@ -1,37 +0,0 @@ +-/****************************************************************************** +- * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: xuxuepeng +- * Create: 2023-07-31 +- * Description: provide grpc sandboxer async wait call mock +- ******************************************************************************/ +- +-#ifndef _ISULAD_TEST_MOCKS_GRPC_SANDBOXER_ASYNC_WAIT_CALL_MOCK_H +-#define _ISULAD_TEST_MOCKS_GRPC_SANDBOXER_ASYNC_WAIT_CALL_MOCK_H +- +-#include +-#include "grpc_async_wait_call.h" +-using namespace sandbox; +- +-// Mock above class +-class SandboxerAsyncWaitCallMock { +-public: +- MOCK_METHOD2(Call, bool(containerd::services::sandbox::v1::Controller::StubInterface &stub, grpc::CompletionQueue &cq)); +- MOCK_METHOD0(HandleResponse, SandboxerAsyncWaitStatus()); +- MOCK_METHOD0(Timeout, bool()); +- MOCK_METHOD2(SandboxExitCallback, void(bool statusOK, const ControllerExitInfo &exitInfo)); +- MOCK_METHOD0(SandboxPendingCallback, void()); +- MOCK_METHOD0(SandboxReadyCallback, void()); +- MOCK_METHOD0(GetSandboxId, const std::string & ()); +-}; +- +-void MockSandboxerAsyncWaitCall_SetMock(std::shared_ptr mock); +- +-#endif // _ISULAD_TEST_MOCKS_GRPC_SANDBOXER_ASYNC_WAIT_CALL_MOCK_H +\ No newline at end of file +diff --git a/test/mocks/grpc_sandboxer_client_mock.cc b/test/mocks/grpc_sandboxer_client_mock.cc +index 03df9048..1f03a00e 100644 +--- a/test/mocks/grpc_sandboxer_client_mock.cc ++++ b/test/mocks/grpc_sandboxer_client_mock.cc +@@ -14,7 +14,6 @@ + ******************************************************************************/ + + #include "grpc_sandboxer_client_mock.h" +-#include "controller_stub_mock.h" + + static std::shared_ptr g_sandboxer_client_mock = NULL; + +@@ -22,24 +21,6 @@ SandboxerClient::SandboxerClient(const std::string &sandboxer, const std::string + { + m_sandboxer = sandboxer; + m_address = address; +- m_channel = grpc::CreateChannel(m_address, grpc::InsecureChannelCredentials()); +- m_stub = NewDummyControllerStub(); +-} +- +-void SandboxerClient::Init(Errors &error) +-{ +- if (g_sandboxer_client_mock == NULL) { +- return; +- } +- g_sandboxer_client_mock->Init(error); +-} +- +-void SandboxerClient::Destroy() +-{ +- if (g_sandboxer_client_mock == NULL) { +- return; +- } +- return g_sandboxer_client_mock->Destroy(); + } + + auto SandboxerClient::Create(const std::string &sandboxId, const ControllerCreateParams ¶ms, Errors &error) -> bool +@@ -67,31 +48,12 @@ auto SandboxerClient::Platform(const std::string &sandboxId, ControllerPlatformI + return g_sandboxer_client_mock->Platform(sandboxId, platformInfo, error); + } + +-auto SandboxerClient::Prepare(const std::string &sandboxId, const ControllerPrepareParams ¶ms, std::string &bundle, +- Errors &error) -> bool ++auto SandboxerClient::Update(sandbox_sandbox *apiSandbox, string_array *fields, Errors &error) -> bool + { + if (g_sandboxer_client_mock == NULL) { + return true; + } +- return g_sandboxer_client_mock->Prepare(sandboxId, params, bundle, error); +-} +- +-auto SandboxerClient::Purge(const std::string &sandboxId, const std::string &containerId, +- const std::string &execId, Errors &error) -> bool +-{ +- if (g_sandboxer_client_mock == NULL) { +- return true; +- } +- return g_sandboxer_client_mock->Purge(sandboxId, containerId, execId, error); +-} +- +-auto SandboxerClient::UpdateResources(const std::string &sandboxId, const ControllerUpdateResourcesParams ¶ms, +- Errors &error) -> bool +-{ +- if (g_sandboxer_client_mock == NULL) { +- return true; +- } +- return g_sandboxer_client_mock->UpdateResources(sandboxId, params, error); ++ return g_sandboxer_client_mock->Update(apiSandbox, fields, error); + } + + auto SandboxerClient::Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) -> bool +@@ -131,4 +93,4 @@ auto SandboxerClient::Shutdown(const std::string &sandboxId, Errors &error) -> b + void MockSandboxerClient_SetMock(std::shared_ptr mock) + { + g_sandboxer_client_mock = mock; +-} +\ No newline at end of file ++} +diff --git a/test/mocks/grpc_sandboxer_client_mock.h b/test/mocks/grpc_sandboxer_client_mock.h +index ac06462a..8d535013 100644 +--- a/test/mocks/grpc_sandboxer_client_mock.h ++++ b/test/mocks/grpc_sandboxer_client_mock.h +@@ -17,23 +17,18 @@ + #define _ISULAD_TEST_MOCKS_GRPC_SANDBOXER_CLIENT_MOCK_H + + #include ++#include ++ + #include "grpc_sandboxer_client.h" + using namespace sandbox; + + class SandboxerClientMock { + public: + SandboxerClientMock() = default; +- MOCK_METHOD1(Init, void(Errors &error)); +- MOCK_METHOD0(Destroy, void()); + MOCK_METHOD3(Create, bool(const std::string &sandboxId, const ControllerCreateParams ¶ms, Errors &error)); + MOCK_METHOD3(Start, bool(const std::string &sandboxId, ControllerSandboxInfo &sandboxInfo, Errors &error)); + MOCK_METHOD3(Platform, bool(const std::string &sandboxId, ControllerPlatformInfo &platformInfo, Errors &error)); +- MOCK_METHOD4(Prepare, bool(const std::string &sandboxId, const ControllerPrepareParams ¶ms, std::string &bundle, +- Errors &error)); +- MOCK_METHOD4(Purge, bool(const std::string &sandboxId, const std::string &containerId, const std::string &execId, +- Errors &error)); +- MOCK_METHOD3(UpdateResources, bool(const std::string &sandboxId, const ControllerUpdateResourcesParams ¶ms, +- Errors &error)); ++ MOCK_METHOD3(Update, bool(sandbox_sandbox *apiSandbox, string_array *fields, Errors &error)); + MOCK_METHOD3(Stop, bool(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error)); + MOCK_METHOD3(Wait, bool(std::shared_ptr cb, const std::string &sandboxId, Errors &error)); + MOCK_METHOD4(Status, bool(const std::string &sandboxId, bool verbose, ControllerSandboxStatus &sandboxStatus, +diff --git a/test/mocks/grpc_sandboxer_monitor_mock.cc b/test/mocks/grpc_sandboxer_monitor_mock.cc +deleted file mode 100644 +index b3ddda87..00000000 +--- a/test/mocks/grpc_sandboxer_monitor_mock.cc ++++ /dev/null +@@ -1,51 +0,0 @@ +-/****************************************************************************** +- * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: xuxuepeng +- * Create: 2023-07-31 +- * Description: provide grpc sandboxer client monitor mock +- ******************************************************************************/ +- +-#include "grpc_sandboxer_monitor_mock.h" +- +-static std::shared_ptr g_sandboxer_client_monitor_mock = NULL; +- +- +-SandboxerClientMonitor::SandboxerClientMonitor(std::shared_ptr channel, const std::string &sandboxer): +- m_channel(channel), m_sandboxer(sandboxer), m_teardown(false) {} +- +-void SandboxerClientMonitor::Start() +-{ +- if (g_sandboxer_client_monitor_mock == NULL) { +- return; +- } +- return g_sandboxer_client_monitor_mock->Start(); +-} +- +-void SandboxerClientMonitor::Stop() +-{ +- if (g_sandboxer_client_monitor_mock == NULL) { +- return; +- } +- return g_sandboxer_client_monitor_mock->Stop(); +-} +- +-bool SandboxerClientMonitor::Monitor(SandboxerAsyncWaitCall *call) +-{ +- if (g_sandboxer_client_monitor_mock == NULL) { +- return true; +- } +- return g_sandboxer_client_monitor_mock->Monitor(call); +-} +- +-void MockSandboxerMonitor_SetMock(std::shared_ptr mock) +-{ +- g_sandboxer_client_monitor_mock = mock; +-} +diff --git a/test/mocks/rust_sandbox_api_mock.cc b/test/mocks/rust_sandbox_api_mock.cc +new file mode 100644 +index 00000000..b595e4b8 +--- /dev/null ++++ b/test/mocks/rust_sandbox_api_mock.cc +@@ -0,0 +1,103 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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-11-22 ++ * Description: provide rust sandbox api mock ++ ******************************************************************************/ ++ ++#include "rust_sandbox_api_mock.h" ++ ++static std::shared_ptr g_rust_sandbox_api_mock = NULL; ++ ++void RustSandboxApiMock_SetMock(std::shared_ptr mock) ++{ ++ g_rust_sandbox_api_mock = mock; ++} ++ ++ControllerHandle_t sandbox_api_build_controller(const char *sandboxer, const char *address) ++{ ++ if (g_rust_sandbox_api_mock != nullptr) { ++ return g_rust_sandbox_api_mock->sandbox_api_build_controller(sandboxer, address); ++ } ++ return nullptr; ++} ++ ++int sandbox_api_create(ControllerHandle_t chandle, const sandbox_create_request *request, sandbox_create_response *response) ++{ ++ if (g_rust_sandbox_api_mock != nullptr) { ++ return g_rust_sandbox_api_mock->sandbox_api_create(chandle, request, response); ++ } ++ return 0; ++} ++ ++int sandbox_api_start(ControllerHandle_t chandle, const sandbox_start_request *request, sandbox_start_response *response) ++{ ++ if (g_rust_sandbox_api_mock != nullptr) { ++ return g_rust_sandbox_api_mock->sandbox_api_start(chandle, request, response); ++ } ++ return 0; ++} ++ ++int sandbox_api_platform(ControllerHandle_t chandle, const sandbox_platform_request *request, sandbox_platform_response *response) ++{ ++ if (g_rust_sandbox_api_mock != nullptr) { ++ return g_rust_sandbox_api_mock->sandbox_api_platform(chandle, request, response); ++ } ++ return 0; ++} ++ ++int sandbox_api_stop(ControllerHandle_t chandle, const sandbox_stop_request *request) ++{ ++ if (g_rust_sandbox_api_mock != nullptr) { ++ return g_rust_sandbox_api_mock->sandbox_api_stop(chandle, request); ++ } ++ return 0; ++} ++ ++int sandbox_api_wait(ControllerHandle_t chandle, const sandbox_wait_request *request, sandbox_api_wait_callback callback) ++{ ++ if (g_rust_sandbox_api_mock != nullptr) { ++ return g_rust_sandbox_api_mock->sandbox_api_wait(chandle, request, callback); ++ } ++ return 0; ++} ++ ++int sandbox_api_status(ControllerHandle_t chandle, const sandbox_status_request *request, sandbox_status_response *response) ++{ ++ if (g_rust_sandbox_api_mock != nullptr) { ++ return g_rust_sandbox_api_mock->sandbox_api_status(chandle, request, response); ++ } ++ return 0; ++} ++ ++int sandbox_api_shutdown(ControllerHandle_t chandle, const sandbox_shutdown_request *request) ++{ ++ if (g_rust_sandbox_api_mock != nullptr) { ++ return g_rust_sandbox_api_mock->sandbox_api_shutdown(chandle, request); ++ } ++ return 0; ++} ++ ++int sandbox_api_metrics(ControllerHandle_t chandle, const sandbox_metrics_request *request, sandbox_metrics_response *response) ++{ ++ if (g_rust_sandbox_api_mock != nullptr) { ++ return g_rust_sandbox_api_mock->sandbox_api_metrics(chandle, request, response); ++ } ++ return 0; ++} ++ ++int sandbox_api_update(ControllerHandle_t chandle, const sandbox_update_request *request) ++{ ++ if (g_rust_sandbox_api_mock != nullptr) { ++ return g_rust_sandbox_api_mock->sandbox_api_update(chandle, request); ++ } ++ return 0; ++} +diff --git a/test/mocks/rust_sandbox_api_mock.h b/test/mocks/rust_sandbox_api_mock.h +new file mode 100644 +index 00000000..134d71e9 +--- /dev/null ++++ b/test/mocks/rust_sandbox_api_mock.h +@@ -0,0 +1,39 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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-11-22 ++ * Description: provide rust sandbox api mock ++ ******************************************************************************/ ++ ++#ifndef _ISULAD_TEST_MOCKS_RUST_SANDBOX_API_MOCK_H ++#define _ISULAD_TEST_MOCKS_RUST_SANDBOX_API_MOCK_H ++ ++#include ++#include ++ ++class RustSandboxApiMock { ++public: ++ RustSandboxApiMock() = default; ++ MOCK_METHOD2(sandbox_api_build_controller, ControllerHandle_t(const char *sandboxer, const char *address)); ++ MOCK_METHOD3(sandbox_api_create, int(ControllerHandle_t chandle, const sandbox_create_request *request, sandbox_create_response *response)); ++ MOCK_METHOD3(sandbox_api_start, int(ControllerHandle_t chandle, const sandbox_start_request *request, sandbox_start_response *response)); ++ MOCK_METHOD2(sandbox_api_stop, int(ControllerHandle_t chandle, const sandbox_stop_request *request)); ++ MOCK_METHOD3(sandbox_api_wait, int(ControllerHandle_t chandle, const sandbox_wait_request *request, sandbox_api_wait_callback callback)); ++ MOCK_METHOD3(sandbox_api_status, int(ControllerHandle_t chandle, const sandbox_status_request *request, sandbox_status_response *response)); ++ MOCK_METHOD2(sandbox_api_shutdown, int(ControllerHandle_t chandle, const sandbox_shutdown_request *request)); ++ MOCK_METHOD3(sandbox_api_metrics, int(ControllerHandle_t chandle, const sandbox_metrics_request *request, sandbox_metrics_response *response)); ++ MOCK_METHOD3(sandbox_api_platform, int(ControllerHandle_t chandle, const sandbox_platform_request *request, sandbox_platform_response *response)); ++ MOCK_METHOD2(sandbox_api_update, int(ControllerHandle_t chandle, const sandbox_update_request *request)); ++}; ++ ++void RustSandboxApiMock_SetMock(std::shared_ptr mock); ++ ++#endif // _ISULAD_TEST_MOCKS_RUST_SANDBOX_API_MOCK_H +diff --git a/test/mocks/sandbox_manager_mock.cc b/test/mocks/sandbox_manager_mock.cc +new file mode 100644 +index 00000000..c3c32e52 +--- /dev/null ++++ b/test/mocks/sandbox_manager_mock.cc +@@ -0,0 +1,42 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: jikai ++ * Create: 2023-10-20 ++ * Description: provide sandboxer controller mock ++ ******************************************************************************/ ++ ++#include "sandbox_manager_mock.h" ++ ++namespace sandbox { ++static std::shared_ptr g_sandbox_manager_mock = nullptr; ++ ++void MockSandboxManager_SetMock(std::shared_ptr mock) ++{ ++ g_sandbox_manager_mock = mock; ++} ++ ++SandboxManager *SandboxManager::GetInstance() noexcept ++{ ++ if (g_sandbox_manager_mock != nullptr) { ++ return g_sandbox_manager_mock->GetInstance(); ++ } ++ return nullptr; ++} ++ ++std::shared_ptr SandboxManager::GetSandbox(const std::string &idOrName) ++{ ++ if (g_sandbox_manager_mock != nullptr) { ++ return g_sandbox_manager_mock->GetSandbox(idOrName); ++ } ++ return nullptr; ++} ++ ++} +diff --git a/test/mocks/grpc_sandboxer_monitor_mock.h b/test/mocks/sandbox_manager_mock.h +similarity index 55% +rename from test/mocks/grpc_sandboxer_monitor_mock.h +rename to test/mocks/sandbox_manager_mock.h +index 0ab21e00..1378d5b7 100644 +--- a/test/mocks/grpc_sandboxer_monitor_mock.h ++++ b/test/mocks/sandbox_manager_mock.h +@@ -8,26 +8,35 @@ + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. +- * Author: xuxuepeng +- * Create: 2023-07-31 +- * Description: provide grpc sandboxer client monitor mock ++ * Author: jikai ++ * Create: 2023-10-20 ++ * Description: provide sandbox manager mock + ******************************************************************************/ + +-#ifndef _ISULAD_TEST_MOCKS_GRPC_SANDBOXER_MONITOR_MOCK_H +-#define _ISULAD_TEST_MOCKS_GRPC_SANDBOXER_MONITOR_MOCK_H ++#ifndef _ISULAD_TEST_MOCKS_SANDBOX_MANAGER_MOCK_H ++#define _ISULAD_TEST_MOCKS_SANDBOX_MANAGER_MOCK_H + + #include +-#include "grpc_sandboxer_monitor.h" ++#include + +-using namespace sandbox; ++#include "sandbox.h" ++#include "sandbox_manager.h" + +-class SandboxerClientMonitorMock { ++namespace sandbox { ++ ++class MockSandboxManager { + public: +- MOCK_METHOD1(Monitor, bool(SandboxerAsyncWaitCall *call)); +- MOCK_METHOD0(Start, void()); +- MOCK_METHOD0(Stop, void()); ++ MockSandboxManager() = default; ++ virtual ~MockSandboxManager() = default; ++ ++ MOCK_METHOD0(GetInstance, SandboxManager *()); ++ ++ MOCK_METHOD1(GetSandbox, std::shared_ptr(const std::string &idOrName)); ++ + }; + +-void MockSandboxerMonitor_SetMock(std::shared_ptr mock); ++void MockSandboxManager_SetMock(std::shared_ptr mock); ++ ++} + +-#endif // _ISULAD_TEST_MOCKS_GRPC_SANDBOXER_MONITOR_MOCK_H ++#endif +\ No newline at end of file +diff --git a/test/mocks/sandboxer_controller_mock.cc b/test/mocks/sandboxer_controller_mock.cc +new file mode 100644 +index 00000000..4f7258d5 +--- /dev/null ++++ b/test/mocks/sandboxer_controller_mock.cc +@@ -0,0 +1,116 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: jikai ++ * Create: 2023-10-20 ++ * Description: provide sandboxer controller mock ++ ******************************************************************************/ ++ ++#include "sandboxer_controller_mock.h" ++ ++namespace sandbox { ++static std::shared_ptr g_sandboxer_controller_mock = nullptr; ++ ++SandboxerController::SandboxerController(const std::string &sandboxer, const std::string &address) ++{ ++} ++ ++SandboxerController::~SandboxerController() ++{ ++} ++ ++void MockSandboxerController_SetMock(std::shared_ptr mock) ++{ ++ g_sandboxer_controller_mock = mock; ++} ++ ++bool SandboxerController::Init(Errors &error) ++{ ++ if (g_sandboxer_controller_mock != nullptr) { ++ return g_sandboxer_controller_mock->Init(error); ++ } ++ return true; ++} ++ ++bool SandboxerController::Create(const std::string &sandboxId, ++ const ControllerCreateParams ¶ms, ++ Errors &error) ++{ ++ if (g_sandboxer_controller_mock != nullptr) { ++ return g_sandboxer_controller_mock->Create(sandboxId, params, error); ++ } ++ return true; ++} ++ ++std::unique_ptr SandboxerController::Start(const std::string &sandboxId, Errors &error) ++{ ++ if (g_sandboxer_controller_mock != nullptr) { ++ return g_sandboxer_controller_mock->Start(sandboxId, error); ++ } ++ return nullptr; ++} ++ ++std::unique_ptr SandboxerController::Platform(const std::string &sandboxId, Errors &error) ++{ ++ if (g_sandboxer_controller_mock != nullptr) { ++ return g_sandboxer_controller_mock->Platform(sandboxId, error); ++ } ++ return nullptr; ++} ++ ++bool SandboxerController::Update(sandbox_sandbox *apiSandbox, ++ string_array *fields, Errors &error) ++{ ++ return g_sandboxer_controller_mock->Update(apiSandbox, fields, error); ++} ++ ++bool SandboxerController::Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) ++{ ++ if (g_sandboxer_controller_mock != nullptr) { ++ return g_sandboxer_controller_mock->Stop(sandboxId, timeoutSecs, error); ++ } ++ return true; ++} ++ ++bool SandboxerController::Wait(std::shared_ptr cb, const std::string &sandboxId, Errors &error) ++{ ++ if (g_sandboxer_controller_mock != nullptr) { ++ return g_sandboxer_controller_mock->Wait(cb, sandboxId, error); ++ } ++ return true; ++} ++ ++std::unique_ptr SandboxerController::Status(const std::string &sandboxId, bool verbose, ++ Errors &error) ++{ ++ if (g_sandboxer_controller_mock != nullptr) { ++ return g_sandboxer_controller_mock->Status(sandboxId, verbose, error); ++ } ++ return nullptr; ++} ++ ++bool SandboxerController::Shutdown(const std::string &sandboxId, Errors &error) ++{ ++ if (g_sandboxer_controller_mock != nullptr) { ++ return g_sandboxer_controller_mock->Shutdown(sandboxId, error); ++ } ++ return true; ++} ++ ++bool SandboxerController::UpdateNetworkSettings(const std::string &sandboxId, const std::string &networkSettings, ++ Errors &error) ++{ ++ if (g_sandboxer_controller_mock != nullptr) { ++ return g_sandboxer_controller_mock->UpdateNetworkSettings(sandboxId, networkSettings, error); ++ } ++ return true; ++} ++ ++} +diff --git a/test/mocks/sandboxer_controller_mock.h b/test/mocks/sandboxer_controller_mock.h +new file mode 100644 +index 00000000..be0f4016 +--- /dev/null ++++ b/test/mocks/sandboxer_controller_mock.h +@@ -0,0 +1,52 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: jikai ++ * Create: 2023-10-20 ++ * Description: provide sandboxer controller mock ++ ******************************************************************************/ ++ ++#ifndef _ISULAD_TEST_MOCKS_SANDBOXER_CONTROLLER_MOCK_H ++#define _ISULAD_TEST_MOCKS_SANDBOXER_CONTROLLER_MOCK_H ++ ++#include ++#include ++ ++#include "sandboxer_controller.h" ++ ++namespace sandbox { ++ ++class MockSandboxerController { ++public: ++ MockSandboxerController() = default; ++ virtual ~MockSandboxerController() = default; ++ ++ MOCK_METHOD1(Init, bool(Errors &error)); ++ MOCK_METHOD3(Create, bool(const std::string &sandboxId, ++ const ControllerCreateParams ¶ms, ++ Errors &error)); ++ MOCK_METHOD2(Start, std::unique_ptr(const std::string &sandboxId, Errors &error)); ++ MOCK_METHOD2(Platform, std::unique_ptr(const std::string &sandboxId, Errors &error)); ++ MOCK_METHOD3(Update, bool(sandbox_sandbox *apiSandbox, ++ string_array *fields, Errors &error)); ++ MOCK_METHOD3(Stop, bool(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error)); ++ MOCK_METHOD3(Wait, bool(std::shared_ptr cb, const std::string &sandboxId, Errors &error)); ++ MOCK_METHOD3(Status, std::unique_ptr(const std::string &sandboxId, bool verbose, ++ Errors &error)); ++ MOCK_METHOD2(Shutdown, bool(const std::string &sandboxId, Errors &error)); ++ MOCK_METHOD3(UpdateNetworkSettings, bool(const std::string &sandboxId, const std::string &networkSettings, ++ Errors &error)); ++}; ++ ++void MockSandboxerController_SetMock(std::shared_ptr mock); ++ ++} ++ ++#endif +\ No newline at end of file +diff --git a/test/mocks/sandboxer_sandbox_mock.cc b/test/mocks/sandboxer_sandbox_mock.cc +new file mode 100644 +index 00000000..cce58842 +--- /dev/null ++++ b/test/mocks/sandboxer_sandbox_mock.cc +@@ -0,0 +1,72 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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-11-21 ++ * Description: provide sandbox mock ++ ******************************************************************************/ ++ ++#include ++#include "sandboxer_sandbox_mock.h" ++ ++namespace sandbox { ++MockSandboxerSandbox *g_sandboxer_sandbox_mock = nullptr; ++ ++SandboxerSandbox::SandboxerSandbox(const std::string id, const std::string &rootdir, const std::string &statedir, const std::string name, ++ const RuntimeInfo info, std::string netMode, std::string netNsPath, const runtime::v1::PodSandboxConfig sandboxConfig, ++ std::string image):Sandbox(id, rootdir, statedir, name, info, netMode, ++ netNsPath, sandboxConfig, image) ++{ ++} ++ ++void MockSandboxerSandbox_SetMock(MockSandboxerSandbox *mock) ++{ ++ g_sandboxer_sandbox_mock = mock; ++} ++ ++void SandboxerSandbox::LoadSandboxTasks() {} ++ ++auto SandboxerSandbox::SaveSandboxTasks() -> bool ++{ ++ if (g_sandboxer_sandbox_mock != nullptr) { ++ return g_sandboxer_sandbox_mock->SaveSandboxTasks(); ++ } ++ return true; ++} ++ ++auto SandboxerSandbox::AddSandboxTasks(sandbox_task *task) -> bool ++{ ++ if (g_sandboxer_sandbox_mock != nullptr) { ++ return g_sandboxer_sandbox_mock->AddSandboxTasks(task); ++ } ++ return true; ++} ++ ++auto SandboxerSandbox::GetAnySandboxTasks() -> std::string ++{ ++ if (g_sandboxer_sandbox_mock != nullptr) { ++ return g_sandboxer_sandbox_mock->GetAnySandboxTasks(); ++ } ++ return std::string("Nothing for sandboxer."); ++} ++ ++void SandboxerSandbox::DeleteSandboxTasks(const char *containerId) {} ++ ++auto SandboxerSandbox::AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool ++{ ++ if (g_sandboxer_sandbox_mock != nullptr) { ++ return g_sandboxer_sandbox_mock->AddSandboxTasksProcess(containerId, processes); ++ } ++ return true; ++} ++ ++void SandboxerSandbox::DeleteSandboxTasksProcess(const char *containerId, const char *execId) {} ++ ++} +\ No newline at end of file +diff --git a/test/mocks/sandboxer_sandbox_mock.h b/test/mocks/sandboxer_sandbox_mock.h +new file mode 100644 +index 00000000..4f76e5fc +--- /dev/null ++++ b/test/mocks/sandboxer_sandbox_mock.h +@@ -0,0 +1,43 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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-11-21 ++ * Description: provide sandbox mock ++ ******************************************************************************/ ++ ++#ifndef _ISULAD_TEST_MOCKS_SANDBOXER_SANDBOX_MOCK_H ++#define _ISULAD_TEST_MOCKS_SANDBOXER_SANDBOX_MOCK_H ++ ++#include ++#include "sandbox_mock.h" ++#include "sandboxer_sandbox.h" ++ ++namespace sandbox { ++ ++class MockSandboxerSandbox : public MockSandbox { ++public: ++ MockSandboxerSandbox() = default; ++ virtual ~MockSandboxerSandbox() = default; ++ ++ MOCK_METHOD0(LoadSandboxTasks, void()); ++ MOCK_METHOD0(SaveSandboxTasks, bool()); ++ MOCK_METHOD1(AddSandboxTasks, bool(sandbox_task *task)); ++ MOCK_METHOD0(GetAnySandboxTasks, std::string()); ++ MOCK_METHOD1(DeleteSandboxTasks, void(const char *containerId)); ++ MOCK_METHOD2(AddSandboxTasksProcess, bool(const char *containerId, sandbox_process *processes)); ++ MOCK_METHOD2(DeleteSandboxTasksProcess, void(const char *containerId, const char *execId)); ++}; ++ ++void MockSandboxerSandbox_SetMock(MockSandboxerSandbox *mock); ++ ++} ++ ++#endif +diff --git a/test/mocks/shim_controller_mock.cc b/test/mocks/shim_controller_mock.cc +index e0ffc563..d9067e22 100644 +--- a/test/mocks/shim_controller_mock.cc ++++ b/test/mocks/shim_controller_mock.cc +@@ -39,13 +39,6 @@ bool ShimController::Init(Errors &error) + return true; + } + +-void ShimController::Destroy() +-{ +- if (g_shim_controller_mock != nullptr) { +- g_shim_controller_mock->Destroy(); +- } +-} +- + bool ShimController::Create(const std::string &sandboxId, + const ControllerCreateParams ¶ms, + Errors &error) +@@ -72,33 +65,10 @@ std::unique_ptr ShimController::Platform(const std::stri + return nullptr; + } + +-std::string ShimController::Prepare(const std::string &sandboxId, +- const ControllerPrepareParams ¶ms, +- Errors &error) +-{ +- if (g_shim_controller_mock != nullptr) { +- return g_shim_controller_mock->Prepare(sandboxId, params, error); +- } +- return ""; +-} +- +-bool ShimController::Purge(const std::string &sandboxId, const std::string &containerId, +- const std::string &execId, Errors &error) ++bool ShimController::Update(sandbox_sandbox *apiSandbox, ++ string_array *fields, Errors &error) + { +- if (g_shim_controller_mock != nullptr) { +- return g_shim_controller_mock->Purge(sandboxId, containerId, execId, error); +- } +- return true; +-} +- +-bool ShimController::UpdateResources(const std::string &sandboxId, +- const ControllerUpdateResourcesParams ¶ms, +- Errors &error) +-{ +- if (g_shim_controller_mock != nullptr) { +- return g_shim_controller_mock->UpdateResources(sandboxId, params, error); +- } +- return true; ++ return g_shim_controller_mock->Update(apiSandbox, fields, error); + } + + bool ShimController::Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) +diff --git a/test/mocks/shim_controller_mock.h b/test/mocks/shim_controller_mock.h +index 6d0de591..d3a1d0a5 100644 +--- a/test/mocks/shim_controller_mock.h ++++ b/test/mocks/shim_controller_mock.h +@@ -29,20 +29,13 @@ public: + virtual ~MockShimController() = default; + + MOCK_METHOD1(Init, bool(Errors &error)); +- MOCK_METHOD0(Destroy, void()); + MOCK_METHOD3(Create, bool(const std::string &sandboxId, + const ControllerCreateParams ¶ms, + Errors &error)); + MOCK_METHOD2(Start, std::unique_ptr(const std::string &sandboxId, Errors &error)); + MOCK_METHOD2(Platform, std::unique_ptr(const std::string &sandboxId, Errors &error)); +- MOCK_METHOD3(Prepare, std::string(const std::string &sandboxId, +- const ControllerPrepareParams ¶ms, +- Errors &error)); +- MOCK_METHOD4(Purge, bool(const std::string &sandboxId, const std::string &containerId, +- const std::string &execId, Errors &error)); +- MOCK_METHOD3(UpdateResources, bool(const std::string &sandboxId, +- const ControllerUpdateResourcesParams ¶ms, +- Errors &error)); ++ MOCK_METHOD3(Update, bool(sandbox_sandbox *apiSandbox, ++ string_array *fields, Errors &error)); + MOCK_METHOD3(Stop, bool(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error)); + MOCK_METHOD3(Wait, bool(std::shared_ptr cb, const std::string &sandboxId, Errors &error)); + MOCK_METHOD3(Status, std::unique_ptr(const std::string &sandboxId, bool verbose, +diff --git a/test/mocks/shim_sandbox_mock.cc b/test/mocks/shim_sandbox_mock.cc +new file mode 100644 +index 00000000..ccefb424 +--- /dev/null ++++ b/test/mocks/shim_sandbox_mock.cc +@@ -0,0 +1,72 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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-11-21 ++ * Description: provide sandbox mock ++ ******************************************************************************/ ++ ++#include ++#include "shim_sandbox_mock.h" ++ ++namespace sandbox { ++MockShimSandbox *g_shim_sandbox_mock = nullptr; ++ ++ShimSandbox::ShimSandbox(const std::string id, const std::string &rootdir, const std::string &statedir, const std::string name, ++ const RuntimeInfo info, std::string netMode, std::string netNsPath, const runtime::v1::PodSandboxConfig sandboxConfig, ++ std::string image):Sandbox(id, rootdir, statedir, name, info, netMode, ++ netNsPath, sandboxConfig, image) ++{ ++} ++ ++void MockShimSandbox_SetMock(MockShimSandbox *mock) ++{ ++ g_shim_sandbox_mock = mock; ++} ++ ++void ShimSandbox::LoadSandboxTasks() {} ++ ++auto ShimSandbox::SaveSandboxTasks() -> bool ++{ ++ if (g_shim_sandbox_mock != nullptr) { ++ return g_shim_sandbox_mock->SaveSandboxTasks(); ++ } ++ return true; ++} ++ ++auto ShimSandbox::AddSandboxTasks(sandbox_task *task) -> bool ++{ ++ if (g_shim_sandbox_mock != nullptr) { ++ return g_shim_sandbox_mock->AddSandboxTasks(task); ++ } ++ return true; ++} ++ ++auto ShimSandbox::GetAnySandboxTasks() -> std::string ++{ ++ if (g_shim_sandbox_mock != nullptr) { ++ return g_shim_sandbox_mock->GetAnySandboxTasks(); ++ } ++ return std::string("Nothing for shim."); ++} ++ ++void ShimSandbox::DeleteSandboxTasks(const char *containerId) {} ++ ++auto ShimSandbox::AddSandboxTasksProcess(const char *containerId, sandbox_process *processes) -> bool ++{ ++ if (g_shim_sandbox_mock != nullptr) { ++ return g_shim_sandbox_mock->AddSandboxTasksProcess(containerId, processes); ++ } ++ return true; ++} ++ ++void ShimSandbox::DeleteSandboxTasksProcess(const char *containerId, const char *execId) {} ++ ++} +\ No newline at end of file +diff --git a/test/mocks/shim_sandbox_mock.h b/test/mocks/shim_sandbox_mock.h +new file mode 100644 +index 00000000..1b16a4cc +--- /dev/null ++++ b/test/mocks/shim_sandbox_mock.h +@@ -0,0 +1,43 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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-11-21 ++ * Description: provide sandbox mock ++ ******************************************************************************/ ++ ++#ifndef _ISULAD_TEST_MOCKS_SHIM_SANDBOX_MOCK_H ++#define _ISULAD_TEST_MOCKS_SHIM_SANDBOX_MOCK_H ++ ++#include ++#include "sandbox_mock.h" ++#include "shim_sandbox.h" ++ ++namespace sandbox { ++ ++class MockShimSandbox : public MockSandbox { ++public: ++ MockShimSandbox() = default; ++ virtual ~MockShimSandbox() = default; ++ ++ MOCK_METHOD0(LoadSandboxTasks, void()); ++ MOCK_METHOD0(SaveSandboxTasks, bool()); ++ MOCK_METHOD1(AddSandboxTasks, bool(sandbox_task *task)); ++ MOCK_METHOD0(GetAnySandboxTasks, std::string()); ++ MOCK_METHOD1(DeleteSandboxTasks, void(const char *containerId)); ++ MOCK_METHOD2(AddSandboxTasksProcess, bool(const char *containerId, sandbox_process *processes)); ++ MOCK_METHOD2(DeleteSandboxTasksProcess, void(const char *containerId, const char *execId)); ++}; ++ ++void MockShimSandbox_SetMock(MockShimSandbox *mock); ++ ++} ++ ++#endif +diff --git a/test/sandbox/controller/CMakeLists.txt b/test/sandbox/controller/CMakeLists.txt +index 0ba23735..d201872b 100644 +--- a/test/sandbox/controller/CMakeLists.txt ++++ b/test/sandbox/controller/CMakeLists.txt +@@ -1,7 +1,5 @@ + project(iSulad_UT) + +-aux_source_directory(${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox/types grpc_sandbox_type_srcs) +-list(APPEND grpc_sandbox_type_srcs ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox.pb.cc) + list(APPEND grpc_sandbox_type_srcs ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/v1/api_v1.pb.cc) + list(APPEND grpc_sandbox_type_srcs ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/gogo.pb.cc) + add_subdirectory(sandboxer) +diff --git a/test/sandbox/controller/controller_common.cc b/test/sandbox/controller/controller_common.cc +index 5f870c34..8621dfd9 100644 +--- a/test/sandbox/controller/controller_common.cc ++++ b/test/sandbox/controller/controller_common.cc +@@ -14,6 +14,7 @@ + ******************************************************************************/ + + #include "controller_common.h" ++#include "utils.h" + + std::unique_ptr CreateTestMountInfo() + { +@@ -43,24 +44,40 @@ std::unique_ptr CreateTestStreamInfo() + return streamInfo; + } + +-std::unique_ptr CreateTestPrepareParams() ++std::unique_ptr> CreateTestUpdateApiSandbox() + { +- std::unique_ptr params(new sandbox::ControllerPrepareParams()); +- params->containerId = DUMMY_CONTAINER_ID; +- params->execId = DUMMY_EXEC_ID; +- params->spec = std::unique_ptr(new std::string("{spec: test}")); +- params->rootfs.push_back(std::move(CreateTestMountInfo())); +- params->rootfs.push_back(std::move(CreateTestMountInfo())); +- params->streamInfo = CreateTestStreamInfo(); +- return params; ++ sandbox_sandbox *apiSandbox = nullptr; ++ ++ auto apiSandbox_wrapper = makeUniquePtrCStructWrapper(free_sandbox_sandbox); ++ if (apiSandbox_wrapper == nullptr) { ++ return nullptr; ++ } ++ apiSandbox = apiSandbox_wrapper->get(); ++ ++ apiSandbox->sandbox_id = util_strdup_s(DUMMY_SANDBOX_ID.c_str()); ++ apiSandbox->sandboxer = util_strdup_s(DUMMY_SANDBOXER.c_str()); ++ ++ return apiSandbox_wrapper; + } + +-std::unique_ptr CreateTestUpdateResourcesParams( +- google::protobuf::Map &annotations) ++std::unique_ptr> CreateTestFields() + { +- std::unique_ptr resources(new std::string("{cpu: 12}")); +- std::unique_ptr params( +- new sandbox::ControllerUpdateResourcesParams{DUMMY_SANDBOX_ID, std::move(resources), annotations} +- ); +- return params; +-} ++ size_t fields_len = 1; ++ string_array *fields = nullptr; ++ ++ auto fields_wrapper = makeUniquePtrCStructWrapper(util_free_string_array); ++ if (fields_wrapper == nullptr) { ++ return nullptr; ++ } ++ fields = fields_wrapper->get(); ++ ++ fields = util_string_array_new(fields_len); ++ if (fields == nullptr) { ++ return nullptr; ++ } ++ if (util_append_string_array(fields, DUMMY_SANDBOX_EXTENSIONS_TASKS.c_str())) { ++ return nullptr; ++ } ++ ++ return fields_wrapper; ++} +\ No newline at end of file +diff --git a/test/sandbox/controller/controller_common.h b/test/sandbox/controller/controller_common.h +index c01ae83c..b41f24e2 100644 +--- a/test/sandbox/controller/controller_common.h ++++ b/test/sandbox/controller/controller_common.h +@@ -16,6 +16,8 @@ + #ifndef _ISULAD_TEST_SANDBOX_CONTROLLER_CONTROLLER_COMMON_H + #define _ISULAD_TEST_SANDBOX_CONTROLLER_CONTROLLER_COMMON_H + #include "controller.h" ++#include "cstruct_wrapper.h" ++#include "utils_array.h" + + const std::string DUMMY_SANDBOX_ID = "604db93a33ec4c7787e4f369338f5887"; + const std::string DUMMY_CONTAINER_ID = "504db93a32ec4c9789e4d369a38f3889"; +@@ -24,6 +26,8 @@ const uint64_t SECOND_TO_NANOS = 1000000000; + const uint64_t DUMMY_CREATE_AT = 1588 * SECOND_TO_NANOS + 1588; + const uint64_t DUMMY_EXITED_AT = 1688 * SECOND_TO_NANOS + 1588; + const std::string DUMMY_TASK_ADDRESS = "vsock://18982:1"; ++const std::string DUMMY_SANDBOXER = "vmm"; ++const std::string DUMMY_SANDBOX_EXTENSIONS_TASKS = "extensions.tasks"; + + std::unique_ptr CreateTestMountInfo(); + +@@ -31,9 +35,8 @@ std::unique_ptr CreateTestCreateParams(); + + std::unique_ptr CreateTestStreamInfo(); + +-std::unique_ptr CreateTestPrepareParams(); ++std::unique_ptr> CreateTestUpdateApiSandbox(); + +-std::unique_ptr CreateTestUpdateResourcesParams( +- google::protobuf::Map &annotations); ++std::unique_ptr> CreateTestFields(); + + #endif // _ISULAD_TEST_SANDBOX_CONTROLLER_CONTROLLER_COMMON_H +\ No newline at end of file +diff --git a/test/sandbox/controller/manager/CMakeLists.txt b/test/sandbox/controller/manager/CMakeLists.txt +index 6e8c9052..1d8ca372 100644 +--- a/test/sandbox/controller/manager/CMakeLists.txt ++++ b/test/sandbox/controller/manager/CMakeLists.txt +@@ -4,14 +4,12 @@ SET(EXE controller_manager_ut) + + add_executable(${EXE} + ${grpc_sandbox_type_srcs} +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox.pb.cc + ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/v1/api_v1.pb.cc + ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/gogo.pb.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/cpputils/errors.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/controller/sandboxer/sandboxer_controller.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/controller/controller_manager.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/sandboxer/controller/sandboxer_controller.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/controller_manager.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/mocks/grpc_sandboxer_client_mock.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/mocks/controller_stub_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/mocks/isulad_config_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/mocks/shim_controller_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/sandbox/controller/controller_common.cc +@@ -25,10 +23,11 @@ target_include_directories(${EXE} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/config + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/entry/cri + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/executor +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/controller +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/controller/sandboxer +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/controller/sandboxer/client +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/controller/shim ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/sandboxer ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/sandboxer/controller ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/sandboxer/controller/client ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/shim/controller + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/common + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/cutils + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/cutils/map +diff --git a/test/sandbox/controller/sandboxer/CMakeLists.txt b/test/sandbox/controller/sandboxer/CMakeLists.txt +index e77c2e6d..11689cae 100644 +--- a/test/sandbox/controller/sandboxer/CMakeLists.txt ++++ b/test/sandbox/controller/sandboxer/CMakeLists.txt +@@ -2,4 +2,3 @@ project(iSulad_UT) + + add_subdirectory(sandboxer_client) + add_subdirectory(sandboxer_controller) +-add_subdirectory(async_wait_call) +diff --git a/test/sandbox/controller/sandboxer/async_wait_call/CMakeLists.txt b/test/sandbox/controller/sandboxer/async_wait_call/CMakeLists.txt +deleted file mode 100644 +index 0631988a..00000000 +--- a/test/sandbox/controller/sandboxer/async_wait_call/CMakeLists.txt ++++ /dev/null +@@ -1,37 +0,0 @@ +-project(iSulad_UT) +- +-SET(EXE sandboxer_client_async_wait_call_ut) +- +-add_executable(${EXE} +- ${grpc_sandbox_type_srcs} +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cpputils/errors.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/mocks/controller_stub_mock.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/async_wait_call_ut.cc) +- +-target_include_directories(${EXE} PUBLIC +- ${GTEST_INCLUDE_DIR} +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/sandbox/controller +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/sandbox/controller/sandboxer/async_wait_call +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/mocks +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/entry/cri +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/controller +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/controller/sandboxer +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/controller/sandboxer/client +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/common +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cutils +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cutils/map +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/sha256 +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cpputils +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/v1 +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/google/protobuf +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox/types +-) +- +-target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${ISULA_LIBUTILS_LIBRARY} libutils_ut -lgrpc -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) +-target_link_libraries(${EXE} -Wl,--as-needed ${ISULAD_ABSL_USED_TARGETS}) +-add_test(NAME ${EXE} COMMAND ${EXE} --gtest_output=xml:${EXE}-Results.xml) +-set_tests_properties(${EXE} PROPERTIES TIMEOUT 120) +diff --git a/test/sandbox/controller/sandboxer/async_wait_call/async_wait_call_ut.cc b/test/sandbox/controller/sandboxer/async_wait_call/async_wait_call_ut.cc +deleted file mode 100644 +index 1a58344c..00000000 +--- a/test/sandbox/controller/sandboxer/async_wait_call/async_wait_call_ut.cc ++++ /dev/null +@@ -1,115 +0,0 @@ +-/****************************************************************************** +- * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: xuxuepeng +- * Create: 2023-08-01 +- * Description: Async wait call UT +- ******************************************************************************/ +- +-#include "gtest/gtest.h" +-#include "grpc_async_wait_call.h" +-#include "dummy_monitor_utils.h" +-#include "controller_stub_mock.h" +-#include "grpc_client_utils.h" +-#include "controller.h" +- +-class SandboxerAsyncWaitCallWrapper : public sandbox::SandboxerAsyncWaitCall { +-public: +- SandboxerAsyncWaitCallWrapper(std::shared_ptr cb, +- const std::string &sandboxId, const std::string &sandboxer) +- : sandbox::SandboxerAsyncWaitCall(cb, sandboxId, sandboxer) {} +- ~SandboxerAsyncWaitCallWrapper() = default; +- +- grpc::ClientAsyncResponseReaderInterface &GetReader() +- { +- return *m_responseReader; +- } +-}; +- +-class AsyncWaitCallTest : public testing::Test { +-protected: +- void SetUp() override +- { +- m_sandboxId = "8040f13d54889ad4cd"; +- m_sandboxer = "test_sandboxer"; +- m_callback = std::shared_ptr(new DummyCallback()); +- m_call = std::unique_ptr(new sandbox::SandboxerAsyncWaitCall(m_callback, m_sandboxId, +- m_sandboxer)); +- m_stub = std::unique_ptr(NewDummyControllerStub()); +- m_stub_mock = std::make_shared(); +- MockControllerStub_SetMock(m_stub_mock); +- } +- +- void TearDown() override +- { +- MockControllerStub_SetMock(nullptr); +- } +- +- std::string m_sandboxId; +- std::string m_sandboxer; +- std::shared_ptr m_callback; +- std::unique_ptr m_call; +- std::unique_ptr m_stub; +- std::shared_ptr m_stub_mock; +- grpc::CompletionQueue m_cq; +-}; +- +-TEST_F(AsyncWaitCallTest, CallStatusOK) +-{ +- auto reader = new DummyClientAsyncResponseReader(); +- auto timestamp = google::protobuf::Timestamp(); +- timestamp.set_seconds(123456); +- reader->SetExitAt(timestamp); +- reader->SetExitStatus(1); +- reader->SetStatus(grpc::Status::OK); +- EXPECT_CALL(*m_stub_mock, PrepareAsyncWaitRaw).WillOnce(testing::Return(reader)); +- EXPECT_TRUE(m_call->Call(*m_stub, m_cq)); +- EXPECT_EQ(m_call->HandleResponse(), sandbox::SANDBOXER_ASYNC_WAIT_STATUS_OK); +- EXPECT_EQ(m_callback->GetStatus(), ASYNC_WAIT_CALL_STATUS_EXIT); +- EXPECT_EQ(m_callback->GetExitStatus(), 1); +- EXPECT_EQ(m_callback->GetExitedAt(), TimestampToNanos(timestamp)); +-} +- +-TEST_F(AsyncWaitCallTest, CallStatusError) +-{ +- auto reader = new DummyClientAsyncResponseReader(); +- reader->SetStatus(grpc::Status(grpc::StatusCode::PERMISSION_DENIED, "Permission denied")); +- EXPECT_CALL(*m_stub_mock, PrepareAsyncWaitRaw).WillOnce(testing::Return(reader)); +- EXPECT_TRUE(m_call->Call(*m_stub, m_cq)); +- EXPECT_EQ(m_call->HandleResponse(), sandbox::SANDBOXER_ASYNC_WAIT_STATUS_ERROR); +- EXPECT_EQ(m_callback->GetStatus(), ASYNC_WAIT_CALL_STATUS_EXIT); +-} +- +-TEST_F(AsyncWaitCallTest, CallStatusNotFound) +-{ +- auto reader = new DummyClientAsyncResponseReader(); +- reader->SetStatus(grpc::Status(grpc::StatusCode::NOT_FOUND, "Not found")); +- EXPECT_CALL(*m_stub_mock, PrepareAsyncWaitRaw).WillOnce(testing::Return(reader)); +- EXPECT_TRUE(m_call->Call(*m_stub, m_cq)); +- EXPECT_EQ(m_call->HandleResponse(), sandbox::SANDBOXER_ASYNC_WAIT_STATUS_NOT_FOUND); +- EXPECT_EQ(m_callback->GetStatus(), ASYNC_WAIT_CALL_STATUS_EXIT); +-} +- +-TEST_F(AsyncWaitCallTest, CallStatusUnavailable) +-{ +- auto reader = new DummyClientAsyncResponseReader(); +- reader->SetStatus(grpc::Status(grpc::StatusCode::UNAVAILABLE, "Unavailable")); +- EXPECT_CALL(*m_stub_mock, PrepareAsyncWaitRaw).WillOnce(testing::Return(reader)); +- EXPECT_TRUE(m_call->Call(*m_stub, m_cq)); +- EXPECT_EQ(m_call->HandleResponse(), sandbox::SANDBOXER_ASYNC_WAIT_STATUS_RETRY); +- EXPECT_EQ(m_callback->GetStatus(), ASYNC_WAIT_CALL_STATUS_PENDING); +-} +- +-TEST_F(AsyncWaitCallTest, CallStatusPrepareAsyncWaitFailed) +-{ +- EXPECT_CALL(*m_stub_mock, PrepareAsyncWaitRaw).WillOnce(testing::Return(nullptr)); +- EXPECT_FALSE(m_call->Call(*m_stub, m_cq)); +- EXPECT_EQ(m_callback->GetStatus(), ASYNC_WAIT_CALL_STATUS_EXIT); +-} +diff --git a/test/sandbox/controller/sandboxer/async_wait_call/dummy_monitor_utils.h b/test/sandbox/controller/sandboxer/async_wait_call/dummy_monitor_utils.h +deleted file mode 100644 +index 7e98d844..00000000 +--- a/test/sandbox/controller/sandboxer/async_wait_call/dummy_monitor_utils.h ++++ /dev/null +@@ -1,121 +0,0 @@ +-/****************************************************************************** +- * Copyright (c) Huawei Technologies Co., Ltd. 2023. 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: xuxuepeng +- * Create: 2023-08-01 +- * Description: provide dummy class definition for monitor unit tests +- *********************************************************************************/ +- +-#ifndef DUMMY_MONITOR_UTILS_H_ +-#define DUMMY_MONITOR_UTILS_H_ +- +-#include "sandbox.pb.h" +-#include "sandbox.grpc.pb.h" +- +-#include "controller.h" +- +-class DummyClientAsyncResponseReader: public +- grpc::ClientAsyncResponseReaderInterface { +-public: +- DummyClientAsyncResponseReader() = default; +- ~DummyClientAsyncResponseReader() = default; +- +- void StartCall() override {} +- +- void ReadInitialMetadata(void *tag) override {} +- +- void Finish(containerd::services::sandbox::v1::ControllerWaitResponse *response, grpc::Status *status, +- void *tag) override +- { +- response->set_exit_status(m_exitStatus); +- response->mutable_exited_at()->CopyFrom(m_exitedAt); +- *status = m_status; +- m_tag = tag; +- } +- +- void SetExitAt(const google::protobuf::Timestamp &exitAt) +- { +- m_exitedAt = exitAt; +- } +- +- void SetExitStatus(uint32_t status) +- { +- m_exitStatus = status; +- } +- +- void SetStatus(grpc::Status status) +- { +- m_status = status; +- } +- +- void *GetTag() +- { +- return m_tag; +- } +- +-private: +- google::protobuf::Timestamp m_exitedAt; +- uint32_t m_exitStatus; +- containerd::services::sandbox::v1::ControllerWaitResponse *m_response; +- grpc::Status m_status; +- void *m_tag; +-}; +- +-enum AsyncWaitCallStatus { +- ASYNC_WAIT_CALL_STATUS_UNKNOWN, +- ASYNC_WAIT_CALL_STATUS_READY, +- ASYNC_WAIT_CALL_STATUS_EXIT, +- ASYNC_WAIT_CALL_STATUS_PENDING, +-}; +- +-class DummyCallback: public sandbox::SandboxStatusCallback { +-public: +- DummyCallback() +- { +- m_status = ASYNC_WAIT_CALL_STATUS_UNKNOWN; +- } +- ~DummyCallback() = default; +- +- void OnSandboxReady() override +- { +- m_status = ASYNC_WAIT_CALL_STATUS_READY; +- } +- void OnSandboxPending() override +- { +- m_status = ASYNC_WAIT_CALL_STATUS_PENDING; +- } +- void OnSandboxExit(const sandbox::ControllerExitInfo &exitInfo) override +- { +- m_status = ASYNC_WAIT_CALL_STATUS_EXIT; +- m_exitStatus = exitInfo.exitStatus; +- m_exitedAt = exitInfo.exitedAt; +- } +- +- AsyncWaitCallStatus GetStatus() +- { +- return m_status; +- } +- +- uint32_t GetExitStatus() +- { +- return m_exitStatus; +- } +- +- uint64_t GetExitedAt() +- { +- return m_exitedAt; +- } +-private: +- AsyncWaitCallStatus m_status; +- uint32_t m_exitStatus; +- uint64_t m_exitedAt; +-}; +- +-#endif // DUMMY_MONITOR_UTILS_H_ +\ No newline at end of file +diff --git a/test/sandbox/controller/sandboxer/sandboxer_client/CMakeLists.txt b/test/sandbox/controller/sandboxer/sandboxer_client/CMakeLists.txt +index 881797c6..3a136489 100644 +--- a/test/sandbox/controller/sandboxer/sandboxer_client/CMakeLists.txt ++++ b/test/sandbox/controller/sandboxer/sandboxer_client/CMakeLists.txt +@@ -4,14 +4,11 @@ SET(EXE controller_sandboxer_client_ut) + + add_executable(${EXE} + ${grpc_sandbox_type_srcs} +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox.pb.cc +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox.grpc.pb.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/controller/sandboxer/client/grpc_client_utils.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/sandboxer/controller/client/grpc_sandboxer_client.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cpputils/errors.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/mocks/controller_stub_mock.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/mocks/grpc_sandboxer_monitor_mock.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/mocks/grpc_async_wait_call_mock.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cpputils/transform.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/mocks/sandbox_manager_mock.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/mocks/rust_sandbox_api_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/sandbox/controller/controller_common.cc + ${CMAKE_CURRENT_SOURCE_DIR}/sandboxer_client_ut.cc) + +@@ -19,10 +16,12 @@ target_include_directories(${EXE} PUBLIC + ${GTEST_INCLUDE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/sandbox/controller + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/mocks ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/config + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/entry/cri +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/controller +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/controller/sandboxer +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/controller/sandboxer/client ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/sandboxer ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/sandboxer/controller ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/sandboxer/controller/client + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/common + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cutils + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cutils/map +@@ -30,9 +29,6 @@ target_include_directories(${EXE} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cpputils + ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri + ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/v1 +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/google/protobuf +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox/types + ) + + target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${ISULA_LIBUTILS_LIBRARY} libutils_ut -lgrpc -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) +diff --git a/test/sandbox/controller/sandboxer/sandboxer_client/sandboxer_client_ut.cc b/test/sandbox/controller/sandboxer/sandboxer_client/sandboxer_client_ut.cc +index 3b02d95d..019e777c 100644 +--- a/test/sandbox/controller/sandboxer/sandboxer_client/sandboxer_client_ut.cc ++++ b/test/sandbox/controller/sandboxer/sandboxer_client/sandboxer_client_ut.cc +@@ -13,21 +13,16 @@ + * Description: Sandboxer client UT + ******************************************************************************/ + ++#include ++ + #include "gtest/gtest.h" +-#include "controller_stub_mock.h" + #include "grpc_sandboxer_client.h" ++#include "grpc_sandboxer_client_mock.h" ++#include "rust_sandbox_api_mock.h" ++#include "sandbox_manager_mock.h" + #include "controller_common.h" + #include "controller.h" +- +-class SandboxerClientWrapper : public sandbox::SandboxerClient { +-public: +- SandboxerClientWrapper(const std::string &sandboxer, const std::string &address) : SandboxerClient(sandboxer, address) +- { +- m_stub = NewDummyControllerStub(); +- } +- +- ~SandboxerClientWrapper() = default; +-}; ++#include "utils.h" + + class ControllerSandboxerClientTest : public testing::Test { + protected: +@@ -35,78 +30,38 @@ protected: + { + m_sandboxer = "sandboxer"; + m_address = "/tmp/sandboxer.sock"; ++ ControllerHandle_t handle_ptr = (ControllerHandle_t)(0x1); // just not nullptr ++ ++ m_sandboxManagerMock = std::make_shared(); ++ MockSandboxManager_SetMock(m_sandboxManagerMock); ++ m_rustSandboxApiMock = std::make_shared(); ++ RustSandboxApiMock_SetMock(m_rustSandboxApiMock); + +- m_sandboxerClient = std::make_shared(m_sandboxer, m_address); +- m_stub = std::make_shared(); +- MockControllerStub_SetMock(m_stub); ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_build_controller).Times(1).WillOnce(testing::DoAll(testing::Return(handle_ptr))); ++ m_sandboxerClient = std::make_shared(m_sandboxer, m_address); + } + + void TearDown() override + { +- MockControllerStub_SetMock(nullptr); ++ MockSandboxManager_SetMock(nullptr); ++ RustSandboxApiMock_SetMock(nullptr); + } + + std::string m_sandboxer; + std::string m_address; +- +- std::shared_ptr m_stub; +- std::shared_ptr m_sandboxerClient; ++ std::shared_ptr m_sandboxerClient; ++ std::shared_ptr m_sandboxManagerMock = nullptr; ++ std::shared_ptr m_rustSandboxApiMock = nullptr; + }; + +-static std::unique_ptr CreateTestGrpcStartResponse() +-{ +- std::unique_ptr response( +- new containerd::services::sandbox::v1::ControllerStartResponse()); +- response->set_sandbox_id(DUMMY_SANDBOX_ID); +- response->set_pid(1); +- response->mutable_created_at()->set_seconds(DUMMY_CREATE_AT / SECOND_TO_NANOS); +- response->mutable_created_at()->set_nanos(DUMMY_CREATE_AT % SECOND_TO_NANOS); +- response->mutable_labels()->insert({"label1", "value1"}); +- return response; +-} +- +-// Create platform response for test. +-static std::unique_ptr CreateTestPlatformResponse() +-{ +- std::unique_ptr response( +- new containerd::services::sandbox::v1::ControllerPlatformResponse() +- ); +- response->mutable_platform()->set_os("linux"); +- response->mutable_platform()->set_architecture("amd64"); +- response->mutable_platform()->set_variant("ubuntu"); +- return response; +-} +- +-// Create status response for test +-static std::unique_ptr CreateTestStatusResponse() +-{ +- std::unique_ptr response( +- new containerd::services::sandbox::v1::ControllerStatusResponse() +- ); +- response->set_sandbox_id(DUMMY_SANDBOX_ID); +- response->set_state("running"); +- response->set_pid(1); +- response->set_task_address(DUMMY_TASK_ADDRESS); +- response->mutable_created_at()->set_seconds(DUMMY_CREATE_AT / SECOND_TO_NANOS); +- response->mutable_created_at()->set_nanos(DUMMY_CREATE_AT % SECOND_TO_NANOS); +- response->mutable_exited_at()->set_seconds(DUMMY_CREATE_AT / SECOND_TO_NANOS); +- response->mutable_exited_at()->set_nanos(DUMMY_CREATE_AT % SECOND_TO_NANOS); +- response->mutable_info()->insert({"info1", "value1"}); +- response->mutable_extra()->set_value("{extra: test}"); +- return response; +-} +- + /************* Unit tests for Create *************/ + TEST_F(ControllerSandboxerClientTest, CreateTestSucceed) + { + Errors err; + std::unique_ptr params = CreateTestCreateParams(); +- // Fake a grpc create response. +- containerd::services::sandbox::v1::ControllerCreateResponse response; +- response.set_sandbox_id(DUMMY_SANDBOX_ID); +- // Set response to return sandbox_id, and return OK for stub_->Create(). +- EXPECT_CALL(*m_stub, Create).Times(1).WillOnce(testing::DoAll(testing::SetArgPointee<2>(response), +- testing::Return(grpc::Status::OK))); ++ ++ // Set response to return sandbox_id, and return OK for sandbox_api_create(). ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_create).Times(1).WillOnce(testing::DoAll(testing::Return(0))); + EXPECT_TRUE(m_sandboxerClient->Create(DUMMY_SANDBOX_ID, *params, err)); + EXPECT_TRUE(err.Empty()); + } +@@ -117,7 +72,7 @@ TEST_F(ControllerSandboxerClientTest, CreateTestNullConfig) + std::unique_ptr params(new sandbox::ControllerCreateParams()); + params->config = nullptr; + // Stub should not be called +- EXPECT_CALL(*m_stub, Create).Times(0); ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_create).Times(0); + EXPECT_FALSE(m_sandboxerClient->Create(DUMMY_SANDBOX_ID, *params, err)); + EXPECT_FALSE(err.Empty()); + EXPECT_THAT(err.GetCMessage(), testing::HasSubstr("Failed to init create request for sandboxer create request")); +@@ -128,13 +83,9 @@ TEST_F(ControllerSandboxerClientTest, CreateTestNullMount) + Errors err; + std::unique_ptr params = CreateTestCreateParams(); + params->mounts.push_back(nullptr); +- containerd::services::sandbox::v1::ControllerCreateRequest request; + // Save request to check mount size. +- EXPECT_CALL(*m_stub, Create).Times(1).WillOnce(testing::DoAll(testing::SaveArg<1>(&request), +- testing::Return(grpc::Status::OK))); ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_create).Times(1).WillOnce(testing::DoAll(testing::Return(0))); + EXPECT_TRUE(m_sandboxerClient->Create(DUMMY_SANDBOX_ID, *params, err)); +- // The nullptr pushed in params should not be counted. +- EXPECT_EQ(request.rootfs_size(), 1); + EXPECT_TRUE(err.Empty()); + } + +@@ -142,22 +93,65 @@ TEST_F(ControllerSandboxerClientTest, CreateTestStatusNotOK) + { + Errors err; + std::unique_ptr params = CreateTestCreateParams(); +- // Fake a grpc create response. +- containerd::services::sandbox::v1::ControllerCreateResponse response; +- response.set_sandbox_id(DUMMY_SANDBOX_ID); +- EXPECT_CALL(*m_stub, Create).Times(1).WillOnce(testing::Return(grpc::Status(grpc::StatusCode::ABORTED, "gRPC Abort"))); ++ ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_create).Times(1).WillOnce(testing::Return(-1)); + EXPECT_FALSE(m_sandboxerClient->Create(DUMMY_SANDBOX_ID, *params, err)); +- EXPECT_THAT(err.GetCMessage(), testing::HasSubstr("gRPC Abort")); + } + + /************* Unit tests for Start *************/ ++static std::unique_ptr> GetMockLabels() ++{ ++ json_map_string_string *labels = nullptr; ++ size_t len = 1; ++ ++ auto labels_wrapper = makeUniquePtrCStructWrapper(free_json_map_string_string); ++ if (labels_wrapper == nullptr) { ++ return nullptr; ++ } ++ labels = labels_wrapper->get(); ++ ++ labels->keys = (char **)util_smart_calloc_s(sizeof(char *), len); ++ if (labels->keys == nullptr) { ++ return nullptr; ++ } ++ labels->keys[0] = util_strdup_s("label1"); ++ labels->values = (char **)util_smart_calloc_s(sizeof(char *), len); ++ if (labels->values == nullptr) { ++ return nullptr; ++ } ++ labels->values[0] = util_strdup_s("value1"); ++ labels->len = len; ++ ++ return labels_wrapper; ++} ++ ++static std::unique_ptr> GetMockSandboxStartResponse() ++{ ++ sandbox_start_response *reponse = nullptr; ++ ++ auto reponse_wrapper = makeUniquePtrCStructWrapper(free_sandbox_start_response); ++ if (reponse_wrapper == nullptr) { ++ return nullptr; ++ } ++ reponse = reponse_wrapper->get(); ++ ++ reponse->sandbox_id = util_strdup_s(DUMMY_SANDBOX_ID.c_str()); ++ reponse->pid = 1; ++ reponse->created_at = DUMMY_CREATE_AT; ++ reponse->address = util_strdup_s(DUMMY_TASK_ADDRESS.c_str()); ++ reponse->version = 0; ++ reponse->labels = GetMockLabels()->move(); ++ ++ return reponse_wrapper; ++} ++ + TEST_F(ControllerSandboxerClientTest, StartTestSucceed) + { + Errors err; + sandbox::ControllerSandboxInfo sandboxInfo; +- std::unique_ptr response = CreateTestGrpcStartResponse(); +- EXPECT_CALL(*m_stub, Start).Times(1).WillOnce(testing::DoAll(testing::SetArgPointee<2>(*response), +- testing::Return(grpc::Status::OK))); ++ ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_start).Times(1).WillOnce(testing::DoAll(testing::SetArgPointee<2>(*(GetMockSandboxStartResponse()->move())), ++ testing::Return(0))); + EXPECT_TRUE(m_sandboxerClient->Start(DUMMY_SANDBOX_ID, sandboxInfo, err)); + EXPECT_TRUE(err.Empty()); + EXPECT_EQ(sandboxInfo.id, DUMMY_SANDBOX_ID); +@@ -171,128 +165,55 @@ TEST_F(ControllerSandboxerClientTest, StartTestStatusNotOK) + { + Errors err; + sandbox::ControllerSandboxInfo sandboxInfo; +- EXPECT_CALL(*m_stub, Start).Times(1).WillOnce(testing::Return(grpc::Status(grpc::StatusCode::ABORTED, "gRPC Abort"))); ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_start).Times(1).WillOnce(testing::Return(-1)); + EXPECT_FALSE(m_sandboxerClient->Start(DUMMY_SANDBOX_ID, sandboxInfo, err)); +- EXPECT_THAT(err.GetCMessage(), testing::HasSubstr("gRPC Abort")); +-} +- +-/************* Unit tests for Prepare *************/ +-TEST_F(ControllerSandboxerClientTest, PrepareTestSucceed) +-{ +- Errors err; +- std::string bundle; +- std::unique_ptr params = CreateTestPrepareParams(); +- // Fake a grpc prepare response. +- containerd::services::sandbox::v1::PrepareResponse response; +- response.set_bundle("/tmp/bundle"); +- // Set response to return bundle, and return OK for stub_->Prepare(). +- EXPECT_CALL(*m_stub, Prepare).Times(1).WillOnce(testing::DoAll(testing::SetArgPointee<2>(response), +- testing::Return(grpc::Status::OK))); +- EXPECT_TRUE(m_sandboxerClient->Prepare(DUMMY_SANDBOX_ID, *params, bundle, err)); +- EXPECT_TRUE(err.Empty()); +- EXPECT_EQ(bundle, "/tmp/bundle"); +-} +- +-TEST_F(ControllerSandboxerClientTest, PrepareTestNullSpec) +-{ +- Errors err; +- std::string bundle; +- std::unique_ptr params = CreateTestPrepareParams(); +- params->spec = nullptr; +- // Stub should not be called +- EXPECT_CALL(*m_stub, Prepare).Times(0); +- EXPECT_FALSE(m_sandboxerClient->Prepare(DUMMY_SANDBOX_ID, *params, bundle, err)); +- EXPECT_THAT(err.GetCMessage(), testing::HasSubstr("Failed to init prepare request for sandboxer prepare request")); + } + +-TEST_F(ControllerSandboxerClientTest, PrepareTestNullMount) ++/************* Unit tests for Update *************/ ++TEST_F(ControllerSandboxerClientTest, UpdateTestSucceed) + { + Errors err; +- std::string bundle; +- std::unique_ptr params = CreateTestPrepareParams(); +- params->rootfs.push_back(nullptr); +- containerd::services::sandbox::v1::PrepareRequest request; +- // Save request to check mount size. +- EXPECT_CALL(*m_stub, Prepare).Times(1).WillOnce(testing::DoAll(testing::SaveArg<1>(&request), +- testing::Return(grpc::Status::OK))); +- EXPECT_TRUE(m_sandboxerClient->Prepare(DUMMY_SANDBOX_ID, *params, bundle, err)); +- // The nullptr pushed in params should not be counted. +- EXPECT_EQ(request.rootfs_size(), 2); ++ auto apiSandbox = CreateTestUpdateApiSandbox(); ++ auto fields = CreateTestFields(); ++ // Set response to return bundle, and return OK for sandbox_api_update(). ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_update).Times(1).WillOnce(testing::DoAll(testing::Return(0))); ++ EXPECT_TRUE(m_sandboxerClient->Update(apiSandbox->get(), fields->get(), err)); + EXPECT_TRUE(err.Empty()); + } + +-TEST_F(ControllerSandboxerClientTest, PrepareTestStatusNotOK) ++TEST_F(ControllerSandboxerClientTest, UpdateTestStatusNotOK) + { + Errors err; +- std::string bundle; +- std::unique_ptr params = CreateTestPrepareParams(); +- EXPECT_CALL(*m_stub, Prepare).Times(1).WillOnce(testing::Return(grpc::Status(grpc::StatusCode::ABORTED, "gRPC Abort"))); +- EXPECT_FALSE(m_sandboxerClient->Prepare(DUMMY_SANDBOX_ID, *params, bundle, err)); +- EXPECT_THAT(err.GetCMessage(), testing::HasSubstr("gRPC Abort")); ++ auto apiSandbox = CreateTestUpdateApiSandbox(); ++ auto fields = CreateTestFields(); ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_update).Times(1).WillOnce(testing::Return(-1)); ++ EXPECT_FALSE(m_sandboxerClient->Update(apiSandbox->get(), fields->get(), err)); + } + +-/************* Unit tests for Purge *************/ +-TEST_F(ControllerSandboxerClientTest, PurgeTestSucceed) +-{ +- Errors err; +- // Set response to return OK for stub_->Purge(). +- EXPECT_CALL(*m_stub, Purge).Times(1).WillOnce(testing::Return(grpc::Status::OK)); +- EXPECT_TRUE(m_sandboxerClient->Purge(DUMMY_SANDBOX_ID, DUMMY_CONTAINER_ID, DUMMY_EXEC_ID, err)); +- EXPECT_TRUE(err.Empty()); +-} +- +-TEST_F(ControllerSandboxerClientTest, PurgeTestStatusNotOK) ++/************* Unit tests for Platform *************/ ++static std::unique_ptr> GetMockSandboxPlatformResponse() + { +- Errors err; +- EXPECT_CALL(*m_stub, Purge).Times(1).WillOnce(testing::Return(grpc::Status(grpc::StatusCode::ABORTED, "gRPC Abort"))); +- EXPECT_FALSE(m_sandboxerClient->Purge(DUMMY_SANDBOX_ID, DUMMY_CONTAINER_ID, DUMMY_EXEC_ID, err)); +- EXPECT_THAT(err.GetCMessage(), testing::HasSubstr("gRPC Abort")); +-} ++ sandbox_platform_response *reponse = nullptr; + +-/************* Unit tests for UpdateResources *************/ +-TEST_F(ControllerSandboxerClientTest, UpdateResourcesTestSucceed) +-{ +- Errors err; +- google::protobuf::Map annotations; +- std::unique_ptr params = CreateTestUpdateResourcesParams(annotations); +- // Set response to return OK for stub_->UpdateResources(). +- EXPECT_CALL(*m_stub, UpdateResources).Times(1).WillOnce(testing::Return(grpc::Status::OK)); +- EXPECT_TRUE(m_sandboxerClient->UpdateResources(DUMMY_SANDBOX_ID, *params, err)); +- EXPECT_TRUE(err.Empty()); +-} ++ auto reponse_wrapper = makeUniquePtrCStructWrapper(free_sandbox_platform_response); ++ if (reponse_wrapper == nullptr) { ++ return nullptr; ++ } ++ reponse = reponse_wrapper->get(); + +-TEST_F(ControllerSandboxerClientTest, UpdateResourcesTestNullResources) +-{ +- Errors err; +- google::protobuf::Map annotations; +- std::unique_ptr params = CreateTestUpdateResourcesParams(annotations); +- params->resources = nullptr; +- // Stub should not be called +- EXPECT_CALL(*m_stub, UpdateResources).Times(0); +- EXPECT_FALSE(m_sandboxerClient->UpdateResources(DUMMY_SANDBOX_ID, *params, err)); +- EXPECT_THAT(err.GetCMessage(), +- testing::HasSubstr("Failed to init update-resources request for sandboxer update-resources request")); +-} ++ reponse->os = util_strdup_s("linux"); ++ reponse->architecture = util_strdup_s("amd64"); ++ reponse->variant = util_strdup_s("ubuntu"); + +-TEST_F(ControllerSandboxerClientTest, UpdateResourcesTestStatusNotOK) +-{ +- Errors err; +- google::protobuf::Map annotations; +- std::unique_ptr params = CreateTestUpdateResourcesParams(annotations); +- EXPECT_CALL(*m_stub, UpdateResources).Times(1).WillOnce(testing::Return(grpc::Status(grpc::StatusCode::ABORTED, +- "gRPC Abort"))); +- EXPECT_FALSE(m_sandboxerClient->UpdateResources(DUMMY_SANDBOX_ID, *params, err)); +- EXPECT_THAT(err.GetCMessage(), testing::HasSubstr("gRPC Abort")); ++ return reponse_wrapper; + } + +-/************* Unit tests for Platform *************/ + TEST_F(ControllerSandboxerClientTest, PlatformTestSucceed) + { + Errors err; + sandbox::ControllerPlatformInfo platformInfo; +- std::unique_ptr response = CreateTestPlatformResponse(); +- EXPECT_CALL(*m_stub, Platform).Times(1).WillOnce(testing::DoAll(testing::SetArgPointee<2>(*response), +- testing::Return(grpc::Status::OK))); ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_platform).Times(1).WillOnce(testing::DoAll(testing::SetArgPointee<2>(*(GetMockSandboxPlatformResponse()->move())), ++ testing::Return(0))); + EXPECT_TRUE(m_sandboxerClient->Platform(DUMMY_SANDBOX_ID, platformInfo, err)); + EXPECT_TRUE(err.Empty()); + EXPECT_EQ(platformInfo.os, "linux"); +@@ -304,18 +225,16 @@ TEST_F(ControllerSandboxerClientTest, PlatformTestStatusNotOK) + { + Errors err; + sandbox::ControllerPlatformInfo platformInfo; +- EXPECT_CALL(*m_stub, Platform).Times(1).WillOnce(testing::Return(grpc::Status(grpc::StatusCode::ABORTED, +- "gRPC Abort"))); ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_platform).Times(1).WillOnce(testing::Return(-1)); + EXPECT_FALSE(m_sandboxerClient->Platform(DUMMY_SANDBOX_ID, platformInfo, err)); +- EXPECT_THAT(err.GetCMessage(), testing::HasSubstr("gRPC Abort")); + } + + /************* Unit tests for Stop *************/ + TEST_F(ControllerSandboxerClientTest, StopTestSucceed) + { + Errors err; +- // Set response to return OK for stub_->Stop(). +- EXPECT_CALL(*m_stub, Stop).Times(1).WillOnce(testing::Return(grpc::Status::OK)); ++ // Set response to return OK for sandbox_api_stop(). ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_stop).Times(1).WillOnce(testing::Return(0)); + EXPECT_TRUE(m_sandboxerClient->Stop(DUMMY_SANDBOX_ID, 0, err)); + EXPECT_TRUE(err.Empty()); + } +@@ -323,19 +242,49 @@ TEST_F(ControllerSandboxerClientTest, StopTestSucceed) + TEST_F(ControllerSandboxerClientTest, StopTestStatusNotOK) + { + Errors err; +- EXPECT_CALL(*m_stub, Stop).Times(1).WillOnce(testing::Return(grpc::Status(grpc::StatusCode::ABORTED, "gRPC Abort"))); ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_stop).Times(1).WillOnce(testing::Return(-1)); + EXPECT_FALSE(m_sandboxerClient->Stop(DUMMY_SANDBOX_ID, 0, err)); +- EXPECT_THAT(err.GetCMessage(), testing::HasSubstr("gRPC Abort")); + } + + /************* Unit tests for Status *************/ ++static std::unique_ptr> GetMockSandboxStatusResponse() ++{ ++ sandbox_status_response *reponse = nullptr; ++ ++ auto reponse_wrapper = makeUniquePtrCStructWrapper(free_sandbox_status_response); ++ if (reponse_wrapper == nullptr) { ++ return nullptr; ++ } ++ reponse = reponse_wrapper->get(); ++ ++ reponse->sandbox_id = util_strdup_s(DUMMY_SANDBOX_ID.c_str()); ++ reponse->pid = 1; ++ reponse->state = util_strdup_s("running"); ++ reponse->info = GetMockLabels()->move(); ++ if (reponse->info == nullptr) { ++ return nullptr; ++ } ++ reponse->created_at = DUMMY_CREATE_AT; ++ reponse->exited_at = DUMMY_CREATE_AT; ++ reponse->extra = (defs_any *)util_common_calloc_s(sizeof(defs_any)); ++ if (reponse->extra == nullptr) { ++ return nullptr; ++ } ++ reponse->extra->value = (uint8_t*)util_strdup_s("{extra: test}"); ++ reponse->extra->value_len = 13; ++ reponse->address = util_strdup_s(DUMMY_TASK_ADDRESS.c_str()); ++ reponse->version = 0; ++ ++ return reponse_wrapper; ++} ++ + TEST_F(ControllerSandboxerClientTest, StatusTestSucceed) + { + Errors err; + sandbox::ControllerSandboxStatus sandboxStatus; +- std::unique_ptr response = CreateTestStatusResponse(); +- EXPECT_CALL(*m_stub, Status).Times(1).WillOnce(testing::DoAll(testing::SetArgPointee<2>(*response), +- testing::Return(grpc::Status::OK))); ++ ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_status).Times(1).WillOnce(testing::DoAll(testing::SetArgPointee<2>(*(GetMockSandboxStatusResponse()->move())), ++ testing::Return(0))); + EXPECT_TRUE(m_sandboxerClient->Status(DUMMY_SANDBOX_ID, false, sandboxStatus, err)); + EXPECT_TRUE(err.Empty()); + EXPECT_EQ(sandboxStatus.id, DUMMY_SANDBOX_ID); +@@ -345,7 +294,7 @@ TEST_F(ControllerSandboxerClientTest, StatusTestSucceed) + EXPECT_EQ(sandboxStatus.createdAt, DUMMY_CREATE_AT); + EXPECT_EQ(sandboxStatus.exitedAt, DUMMY_CREATE_AT); + EXPECT_EQ(sandboxStatus.info.size(), 1); +- EXPECT_EQ(sandboxStatus.info["info1"], "value1"); ++ EXPECT_EQ(sandboxStatus.info["label1"], "value1"); + EXPECT_EQ(sandboxStatus.extra, "{extra: test}"); + } + +@@ -353,17 +302,16 @@ TEST_F(ControllerSandboxerClientTest, StatusTestStatusNotOK) + { + Errors err; + sandbox::ControllerSandboxStatus sandboxStatus; +- EXPECT_CALL(*m_stub, Status).Times(1).WillOnce(testing::Return(grpc::Status(grpc::StatusCode::ABORTED, "gRPC Abort"))); ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_status).Times(1).WillOnce(testing::Return(-1)); + EXPECT_FALSE(m_sandboxerClient->Status(DUMMY_SANDBOX_ID, false, sandboxStatus, err)); +- EXPECT_THAT(err.GetCMessage(), testing::HasSubstr("gRPC Abort")); + } + + /************* Unit tests for Shutdown *************/ + TEST_F(ControllerSandboxerClientTest, ShutdownTestSucceed) + { + Errors err; +- // Set response to return OK for stub_->Shutdown(). +- EXPECT_CALL(*m_stub, Shutdown).Times(1).WillOnce(testing::Return(grpc::Status::OK)); ++ // Set response to return OK for sandbox_api_shutdown(). ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_shutdown).Times(1).WillOnce(testing::Return(0)); + EXPECT_TRUE(m_sandboxerClient->Shutdown(DUMMY_SANDBOX_ID, err)); + EXPECT_TRUE(err.Empty()); + } +@@ -371,8 +319,6 @@ TEST_F(ControllerSandboxerClientTest, ShutdownTestSucceed) + TEST_F(ControllerSandboxerClientTest, ShutdownTestStatusNotOK) + { + Errors err; +- EXPECT_CALL(*m_stub, Shutdown).Times(1).WillOnce(testing::Return(grpc::Status(grpc::StatusCode::ABORTED, +- "gRPC Abort"))); ++ EXPECT_CALL(*m_rustSandboxApiMock, sandbox_api_shutdown).Times(1).WillOnce(testing::Return(-1)); + EXPECT_FALSE(m_sandboxerClient->Shutdown(DUMMY_SANDBOX_ID, err)); +- EXPECT_THAT(err.GetCMessage(), testing::HasSubstr("gRPC Abort")); + } +diff --git a/test/sandbox/controller/sandboxer/sandboxer_controller/CMakeLists.txt b/test/sandbox/controller/sandboxer/sandboxer_controller/CMakeLists.txt +index 963ce9a5..e03cc58e 100644 +--- a/test/sandbox/controller/sandboxer/sandboxer_controller/CMakeLists.txt ++++ b/test/sandbox/controller/sandboxer/sandboxer_controller/CMakeLists.txt +@@ -4,13 +4,11 @@ SET(EXE sandbox_controller_ut) + + add_executable(${EXE} + ${grpc_sandbox_type_srcs} +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox.pb.cc + ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/v1/api_v1.pb.cc + ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/gogo.pb.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cpputils/errors.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/controller/sandboxer/sandboxer_controller.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/sandboxer/controller/sandboxer_controller.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/mocks/grpc_sandboxer_client_mock.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/mocks/controller_stub_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/sandbox/controller/controller_common.cc + ${CMAKE_CURRENT_SOURCE_DIR}/sandboxer_controller_ut.cc) + +@@ -19,9 +17,10 @@ target_include_directories(${EXE} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/sandbox/controller + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../test/mocks + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/entry/cri +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/controller +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/controller/sandboxer +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/controller/sandboxer/client ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/sandboxer ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/sandboxer/controller ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/daemon/sandbox/sandboxer/controller/client + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/common + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cutils + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cutils/map +diff --git a/test/sandbox/controller/sandboxer/sandboxer_controller/sandboxer_controller_ut.cc b/test/sandbox/controller/sandboxer/sandboxer_controller/sandboxer_controller_ut.cc +index f49d7cc5..726464e8 100644 +--- a/test/sandbox/controller/sandboxer/sandboxer_controller/sandboxer_controller_ut.cc ++++ b/test/sandbox/controller/sandboxer/sandboxer_controller/sandboxer_controller_ut.cc +@@ -27,8 +27,6 @@ protected: + m_contoller = std::move(std::unique_ptr(new SandboxerController(m_sandboxer, m_address))); + m_sandboxerClientMock = std::make_shared(); + MockSandboxerClient_SetMock(m_sandboxerClientMock); +- EXPECT_CALL(*m_sandboxerClientMock, Init).Times(1); +- m_contoller->Init(err); + } + + void TearDown() override +@@ -119,61 +117,27 @@ TEST_F(SandboxerControllerTest, PlatformTestFailed) + EXPECT_EQ(ret, nullptr); + } + +-/************* Unit tests for Prepare *************/ +-TEST_F(SandboxerControllerTest, PrepareTestSucceed) ++/************* Unit tests for Update *************/ ++TEST_F(SandboxerControllerTest, UpdateTestSucceed) + { + Errors err; +- std::string bundle = "/tmp/bundle"; +- // Set response to return sandbox_id, and return OK for stub_->Prepare(). +- EXPECT_CALL(*m_sandboxerClientMock, Prepare).Times(1).WillOnce(testing::DoAll(testing::SetArgReferee<2>(bundle), +- testing::Return(true))); +- std::string ret = m_contoller->Prepare(DUMMY_SANDBOX_ID, *CreateTestPrepareParams(), err); +- EXPECT_EQ(ret, bundle); +-} +- +-TEST_F(SandboxerControllerTest, PrepareTestFailed) +-{ +- Errors err; +- // Set response to return sandbox_id, and return OK for stub_->Prepare(). +- EXPECT_CALL(*m_sandboxerClientMock, Prepare).Times(1).WillOnce(testing::Return(false)); +- std::string ret = m_contoller->Prepare(DUMMY_SANDBOX_ID, *CreateTestPrepareParams(), err); +- EXPECT_EQ(ret, ""); +-} +- +-/************* Unit tests for Purge *************/ +-TEST_F(SandboxerControllerTest, PurgeTestSucceed) +-{ +- Errors err; +- // Set response to return sandbox_id, and return OK for stub_->Purge(). +- EXPECT_CALL(*m_sandboxerClientMock, Purge).Times(1).WillOnce(testing::Return(true)); +- EXPECT_TRUE(m_contoller->Purge(DUMMY_SANDBOX_ID, DUMMY_CONTAINER_ID, DUMMY_EXEC_ID, err)); +-} ++ auto apiSandbox = CreateTestUpdateApiSandbox(); ++ auto fields = CreateTestFields(); + +-TEST_F(SandboxerControllerTest, PurgeTestFailed) +-{ +- Errors err; +- // Set response to return sandbox_id, and return OK for stub_->Purge(). +- EXPECT_CALL(*m_sandboxerClientMock, Purge).Times(1).WillOnce(testing::Return(false)); +- EXPECT_FALSE(m_contoller->Purge(DUMMY_SANDBOX_ID, DUMMY_CONTAINER_ID, DUMMY_EXEC_ID, err)); ++ // return OK for stub_->Update(). ++ EXPECT_CALL(*m_sandboxerClientMock, Update).Times(1).WillOnce(testing::DoAll(testing::Return(true))); ++ EXPECT_TRUE(m_contoller->Update(apiSandbox->get(), fields->get(), err)); + } + +-/************* Unit tests for UpdateResources *************/ +-TEST_F(SandboxerControllerTest, UpdateResourcesTestSucceed) ++TEST_F(SandboxerControllerTest, UpdateTestFailed) + { + Errors err; +- google::protobuf::Map annotations; +- // Set response to return sandbox_id, and return OK for stub_->UpdateResources(). +- EXPECT_CALL(*m_sandboxerClientMock, UpdateResources).Times(1).WillOnce(testing::Return(true)); +- EXPECT_TRUE(m_contoller->UpdateResources(DUMMY_SANDBOX_ID, *CreateTestUpdateResourcesParams(annotations), err)); +-} ++ auto apiSandbox = CreateTestUpdateApiSandbox(); ++ auto fields = CreateTestFields(); + +-TEST_F(SandboxerControllerTest, UpdateResourcesTestFailed) +-{ +- Errors err; +- google::protobuf::Map annotations; +- // Set response to return sandbox_id, and return OK for stub_->UpdateResources(). +- EXPECT_CALL(*m_sandboxerClientMock, UpdateResources).Times(1).WillOnce(testing::Return(false)); +- EXPECT_FALSE(m_contoller->UpdateResources(DUMMY_SANDBOX_ID, *CreateTestUpdateResourcesParams(annotations), err)); ++ // return OK for stub_->Update(). ++ EXPECT_CALL(*m_sandboxerClientMock, Update).Times(1).WillOnce(testing::Return(false)); ++ EXPECT_FALSE(m_contoller->Update(apiSandbox->get(), fields->get(), err)); + } + + /************* Unit tests for Stop *************/ +diff --git a/test/sandbox/controller/shim/CMakeLists.txt b/test/sandbox/controller/shim/CMakeLists.txt +index d18d1861..069312c9 100644 +--- a/test/sandbox/controller/shim/CMakeLists.txt ++++ b/test/sandbox/controller/shim/CMakeLists.txt +@@ -14,7 +14,7 @@ add_executable(${EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/common/err_msg.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/config/daemon_arguments.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/config/isulad_config.c +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/controller/shim/shim_controller.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/shim/controller/shim_controller.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/cpputils/errors.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/cpputils/cxxutils.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/sha256/sha256.c +@@ -41,8 +41,9 @@ target_include_directories(${EXE} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2 + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/controller +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/controller/shim ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/shim ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/sandbox/shim/controller + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/cpputils + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/sha256 + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../test/sandbox/controller +diff --git a/test/sandbox/sandbox/CMakeLists.txt b/test/sandbox/sandbox/CMakeLists.txt +index 2a35388f..9ee67033 100644 +--- a/test/sandbox/sandbox/CMakeLists.txt ++++ b/test/sandbox/sandbox/CMakeLists.txt +@@ -6,7 +6,6 @@ aux_source_directory(${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox/t + + add_executable(${EXE} + ${sandbox_type_srcs} +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox.pb.cc + ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/v1/api_v1.pb.cc + ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/gogo.pb.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cpputils/errors.cc +@@ -14,14 +13,15 @@ add_executable(${EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cpputils/transform.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cpputils/cxxutils.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/sandbox.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller/controller_manager.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller/sandboxer/sandboxer_controller.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/sandbox_task.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller_manager.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/sandboxer/controller/sandboxer_controller.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/shim/shim_sandbox.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/common/id_name_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/config/isulad_config.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/sandbox/controller/controller_common.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/config/daemon_arguments.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/grpc_sandboxer_client_mock.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/controller_stub_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/shim_controller_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/mailbox_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/common/err_msg.c +@@ -35,18 +35,17 @@ target_include_directories(${EXE} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/entry/cri + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/executor + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/mailbox +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller/shim +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller/sandboxer +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller/sandboxer/client ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/shim ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/shim/controller ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/sandboxer ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/sandboxer/controller ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/sandboxer/controller/client + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/common + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cpputils + ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri + ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/v1 +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/google/protobuf +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox/types + ) + + target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${ISULA_LIBUTILS_LIBRARY} libutils_ut -lgrpc -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) +diff --git a/test/sandbox/sandbox/sandbox_ut.cc b/test/sandbox/sandbox/sandbox_ut.cc +index dd84d8fb..192d46ef 100644 +--- a/test/sandbox/sandbox/sandbox_ut.cc ++++ b/test/sandbox/sandbox/sandbox_ut.cc +@@ -16,6 +16,7 @@ + #include + + #include "sandbox.h" ++#include "shim_sandbox.h" + + namespace sandbox { + +@@ -40,7 +41,7 @@ TEST_F(SandboxTest, TestDefaultGetters) + std::string name = "test"; + RuntimeInfo info = {"runc", "shim", "kuasar"}; + +- auto sandbox = new Sandbox(id, rootdir, statedir, name, info); ++ auto sandbox = new ShimSandbox(id, rootdir, statedir, name, info); + ASSERT_NE(sandbox, nullptr); + + ASSERT_EQ(sandbox->IsReady(), false); +@@ -66,7 +67,7 @@ TEST_F(SandboxTest, TestGettersAndSetters) + std::string statedir = "/test2/statedir"; + std::string mode = "host"; + +- auto sandbox = new Sandbox(id, rootdir, statedir); ++ auto sandbox = new ShimSandbox(id, rootdir, statedir); + ASSERT_NE(sandbox, nullptr); + + sandbox->SetNetMode(mode); +diff --git a/test/sandbox/sandbox_manager/CMakeLists.txt b/test/sandbox/sandbox_manager/CMakeLists.txt +index 5a7cb2ea..9254263c 100644 +--- a/test/sandbox/sandbox_manager/CMakeLists.txt ++++ b/test/sandbox/sandbox_manager/CMakeLists.txt +@@ -6,22 +6,22 @@ aux_source_directory(${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox/t + + add_executable(${EXE} + ${sandbox_type_srcs} +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox.pb.cc + ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/v1/api_v1.pb.cc + ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/gogo.pb.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cpputils/errors.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cpputils/read_write_lock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cpputils/transform.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/sandbox_mock.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/shim_sandbox_mock.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/sandboxer_sandbox_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/sandbox_manager.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/common/id_name_manager.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/isulad_config_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/common/err_msg.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/config/daemon_arguments.c +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller/controller_manager.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller/sandboxer/sandboxer_controller.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller_manager.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/grpc_sandboxer_client_mock.cc +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/controller_stub_mock.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/sandboxer_controller_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/shim_controller_mock.cc + ${CMAKE_CURRENT_SOURCE_DIR}/sandbox_manager_ut.cc) + +@@ -33,18 +33,17 @@ target_include_directories(${EXE} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/config + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/entry/cri + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/executor +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller/shim +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller/sandboxer +- ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/controller/sandboxer/client ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/shim ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/shim/controller ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/sandboxer ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/sandboxer/controller ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox/sandboxer/controller/client + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/sandbox + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/common + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cpputils + ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri + ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/v1 +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/google/protobuf +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/sandbox/sandbox/types + ) + set_target_properties(${EXE} PROPERTIES LINK_FLAGS "-Wl,--wrap,util_list_all_subdir") + target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${ISULA_LIBUTILS_LIBRARY} libutils_ut -lgrpc -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) +-- +2.34.1 + diff --git a/iSulad.spec b/iSulad.spec index ce59b9c49f03dba8dc70d871ebc4cb41e6825631..d135cb4ab961e11471cfdd113e8ca75fd25d05f9 100644 --- a/iSulad.spec +++ b/iSulad.spec @@ -1,5 +1,5 @@ %global _version 2.1.5 -%global _release 13 +%global _release 14 %global is_systemd 1 %global enable_criv1 1 %global enable_cdi 1 @@ -9,6 +9,7 @@ %ifarch x86_64 aarch64 %global enable_nri 1 +%global enable_sandboxer 1 %endif Name: iSulad @@ -161,6 +162,21 @@ Patch0138: 0138-bugfix-for-log-in-make_safedir_is_noexec.patch Patch0139: 0139-containers-in-paused-state-are-not-allowed-to-start.patch Patch0140: 0140-remove-meaningless-code.patch Patch0141: 0141-fix-unqualified-call-to-std-move.patch +Patch0142: 0142-pull-failure-shows-error-reason.patch +Patch0143: 0143-move-CGROUP2_SUPER_MAGIC-define-to-cgroup.c.patch +Patch0144: 0144-update-centos-build-script.patch +Patch0145: 0145-cni-change-error-info.patch +Patch0146: 0146-bugfix-for-sem_wait-call-when-errno-is-EINTR.patch +Patch0147: 0147-add-no-pivot-root-support.patch +Patch0148: 0148-fix-issues-Isula-ps-cannot-display-port-mapping.patch +Patch0149: 0149-move-nri-call-in-stop-and-remove-con.patch +Patch0150: 0150-add-missing-con-linux-info-for-nri-module.patch +Patch0151: 0151-sandbox-sandbox-api-update.patch +Patch0152: 0152-add-omitted-macro-definition.patch +Patch0153: 0153-sandbox-sandbox-api-adapt-rust-interface.patch +Patch0154: 0154-add-linux-capability.h-head-file.patch +Patch0155: 0155-sandbox-fix-unused-variables.patch +Patch0156: 0156-sandbox-sandbox-api-adapt-rust-interface-UT.patch %ifarch x86_64 aarch64 Provides: libhttpclient.so()(64bit) @@ -243,6 +259,9 @@ cd build %if 0%{?enable_nri} -DENABLE_NRI=ON \ %endif +%if 0%{?enable_sandboxer} + -DENABLE_SANDBOXER=ON \ +%endif %endif %if 0%{?enable_shimv2} -DENABLE_SHIM_V2=ON \ @@ -425,6 +444,12 @@ fi %endif %changelog +* Mon Nov 25 2024 liuxu - 2.1.5-14 +- Type: update +- ID: NA +- SUG: NA +- DESC: upgrade from upstream + * Thu Nov 21 2024 zhongtao - 2.1.5-13 - Type: bugfix - ID: NA