From c56563a5cfb85fcba9f28dd1df9647037eb2931e Mon Sep 17 00:00:00 2001 From: CoprDistGit Date: Sat, 20 Jan 2024 09:57:05 +0000 Subject: automatic import of iSulad --- .gitignore | 1 + ...ox-del-m_containers-and-m_containersMutex.patch | 347 ++ ...pt-UT-when-del-m_containers-and-m_contain.patch | 167 + ...y-Masked-Path-and-RunAsGroup-support-for-.patch | 642 ++++ 0004-network-support-version-opt.patch | 482 +++ 0005-doc-support-version-opt.patch | 87 + ...42-disable-grpc-remote-connect-by-default.patch | 26 + 0007-2244-Save-task-address-of-shim-v2.patch | 209 ++ ...-2233-add-runc-append-function-design-doc.patch | 110 + 0009-2243-Refactor-capbilities-specs.patch | 1056 ++++++ ...ils_verify_ut-failure-when-remote-grpc-fu.patch | 33 + 0011-add-runc-attach-implement.patch | 1312 ++++++++ ...nc-attach-implement-unit-test-and-ci-test.patch | 242 ++ 0013-support-gcov-of-CI.patch | 26 + ...ty-for-manage-pods-which-created-by-old-i.patch | 163 + ...250-Remove-PERFMON-BPF-CHECKPOINT_RESTORE.patch | 33 + 0016-improve-event-logs.patch | 202 ++ ...251-open-ENABLE_GRPC_REMOTE_CONNECT-in-CI.patch | 57 + ...-Add-compatibility-between-iSulad-and-k8s.patch | 57 + ...ntainer-with-a-damaged-config-file-will-r.patch | 384 +++ 0020-2253-bugfix-for-runc-container-exec.patch | 39 + ...pdate-restart-policy-for-auto-remove-cont.patch | 58 + 0022-add-update-restart-policy-test.patch | 57 + 0023-2260-bugfix-for-rebuild-config.patch | 73 + 0024-2170-isula-image-pull.patch | 1815 ++++++++++ 0025-2084-image-pull.patch | 84 + 0026-CI-add-ncurse-for-ubuntu-and-centos.patch | 39 + 0027-improve-code-of-pull-progress.patch | 631 ++++ 0028-2230-format-code.patch | 3476 ++++++++++++++++++++ 0029-2255-Fix-cpusets-offline-issue.patch | 445 +++ ...odify-daemon-json-default-runtime-to-runc.patch | 52 + 0031-modify-CI-for-default-runtime-to-runc.patch | 815 +++++ 0032-add-ut-for-devicemapper.patch | 737 +++++ 0033-2275-bugfix-for-rt_lcr_rebuild_config.patch | 46 + 0034-2277-remove-shim-v2-format-error-log.patch | 25 + 0035-2276-bugfix-for-integration_check.sh.patch | 26 + ...te_network.sh-for-default-runtime-changed.patch | 40 + ...container-runtime-when-running-embedded.s.patch | 141 + ...-save-sandbox-to-disk-after-network-ready.patch | 68 + ...blem-of-abnormal-branches-not-waiting-for.patch | 153 + 0040-remove-embedded-image-support-in-readme.patch | 62 + 0041-Acquire-system-info-in-on-demand.patch | 392 +++ ...-for-the-bliko-zero-value-exception-when-.patch | 92 + 0043-move-variable-declaration-out-of-loop.patch | 34 + ...protobuf-and-grpc-version-in-cmake-for-cr.patch | 40 + 0045-improve-ut-for-devicemapper.patch | 381 +++ ...-for-run.sh-and-add-build-notify-msg-for-.patch | 56 + ...he-service-status-unchanged-after-iSulad-.patch | 251 ++ 0048-modify-attach-socket-name.patch | 40 + ...-for-hook_ignore_poststart_error-run-in-o.patch | 110 + 0050-2304-remove-build-and-test-in-coverage.patch | 28 + ...timeout-epoll-loop-to-ensure-complete-dat.patch | 197 ++ ...default-value-of-ISULAD_TMPDIR-to-var-lib.patch | 170 + ...-parent-dir-from-being-bind-mounted-to-th.patch | 58 + 0054-2308-Remove-unused-header-file.patch | 25 + ...he-mount-dir-first-and-then-create-tmpdir.patch | 43 + 0056-2300-Maintaining-a-uniform-code-style.patch | 26 + ...-Huawei-Cloud-CodeArts-compilation-script.patch | 36 + 0058-bugfix-del-redundant-code.patch | 26 + 0059-improve-code-of-pull.patch | 71 + ...var-in-coverage-and-fix-build-test-remove.patch | 30 + 0061-2320-improve-CI-test.patch | 165 + 0062-verify-name-and-digest-consistency.patch | 319 ++ 0063-code-improve-for-oci_rmi.patch | 35 + 0064-bugfix-for-resort_image_names.patch | 26 + ...emoves-cont-error-remove-inspect-error-lo.patch | 76 + 0066-2313-use-lxc-5.X-in-CI-testcase.patch | 41 + ...29-modify-mount-dev-directory-for-lxc-5.X.patch | 27 + 0068-add-cri-1.29-api-change-docs.patch | 139 + ...-add-exec-workdir-support-for-oci-runtime.patch | 57 + 0070-add-testcases-for-exec-workdir.patch | 27 + ...restart-isuald-when-upgrade-active-isulad.patch | 34 + iSulad.spec | 1000 ++++++ sources | 1 + 74 files changed, 18571 insertions(+) create mode 100644 0001-sandbox-del-m_containers-and-m_containersMutex.patch create mode 100644 0002-sandbox-adapt-UT-when-del-m_containers-and-m_contain.patch create mode 100644 0003-Add-Readonly-Masked-Path-and-RunAsGroup-support-for-.patch create mode 100644 0004-network-support-version-opt.patch create mode 100644 0005-doc-support-version-opt.patch create mode 100644 0006-2242-disable-grpc-remote-connect-by-default.patch create mode 100644 0007-2244-Save-task-address-of-shim-v2.patch create mode 100644 0008-2233-add-runc-append-function-design-doc.patch create mode 100644 0009-2243-Refactor-capbilities-specs.patch create mode 100644 0010-2245-fix-utils_verify_ut-failure-when-remote-grpc-fu.patch create mode 100644 0011-add-runc-attach-implement.patch create mode 100644 0012-add-runc-attach-implement-unit-test-and-ci-test.patch create mode 100644 0013-support-gcov-of-CI.patch create mode 100644 0014-compatibility-for-manage-pods-which-created-by-old-i.patch create mode 100644 0015-2250-Remove-PERFMON-BPF-CHECKPOINT_RESTORE.patch create mode 100644 0016-improve-event-logs.patch create mode 100644 0017-2251-open-ENABLE_GRPC_REMOTE_CONNECT-in-CI.patch create mode 100644 0018-Add-compatibility-between-iSulad-and-k8s.patch create mode 100644 0019-2254-lcr-container-with-a-damaged-config-file-will-r.patch create mode 100644 0020-2253-bugfix-for-runc-container-exec.patch create mode 100644 0021-bugfix-of-update-restart-policy-for-auto-remove-cont.patch create mode 100644 0022-add-update-restart-policy-test.patch create mode 100644 0023-2260-bugfix-for-rebuild-config.patch create mode 100644 0024-2170-isula-image-pull.patch create mode 100644 0025-2084-image-pull.patch create mode 100644 0026-CI-add-ncurse-for-ubuntu-and-centos.patch create mode 100644 0027-improve-code-of-pull-progress.patch create mode 100644 0028-2230-format-code.patch create mode 100644 0029-2255-Fix-cpusets-offline-issue.patch create mode 100644 0030-modify-daemon-json-default-runtime-to-runc.patch create mode 100644 0031-modify-CI-for-default-runtime-to-runc.patch create mode 100644 0032-add-ut-for-devicemapper.patch create mode 100644 0033-2275-bugfix-for-rt_lcr_rebuild_config.patch create mode 100644 0034-2277-remove-shim-v2-format-error-log.patch create mode 100644 0035-2276-bugfix-for-integration_check.sh.patch create mode 100644 0036-modify-create_network.sh-for-default-runtime-changed.patch create mode 100644 0037-modify-the-container-runtime-when-running-embedded.s.patch create mode 100644 0038-save-sandbox-to-disk-after-network-ready.patch create mode 100644 0039-fix-the-problem-of-abnormal-branches-not-waiting-for.patch create mode 100644 0040-remove-embedded-image-support-in-readme.patch create mode 100644 0041-Acquire-system-info-in-on-demand.patch create mode 100644 0042-2268-bugfix-for-the-bliko-zero-value-exception-when-.patch create mode 100644 0043-move-variable-declaration-out-of-loop.patch create mode 100644 0044-2289-check-protobuf-and-grpc-version-in-cmake-for-cr.patch create mode 100644 0045-improve-ut-for-devicemapper.patch create mode 100644 0046-2292-bugfix-for-run.sh-and-add-build-notify-msg-for-.patch create mode 100644 0047-2295-keep-the-service-status-unchanged-after-iSulad-.patch create mode 100644 0048-modify-attach-socket-name.patch create mode 100644 0049-2298-bugfix-for-hook_ignore_poststart_error-run-in-o.patch create mode 100644 0050-2304-remove-build-and-test-in-coverage.patch create mode 100644 0051-2303-use-a-timeout-epoll-loop-to-ensure-complete-dat.patch create mode 100644 0052-modify-the-default-value-of-ISULAD_TMPDIR-to-var-lib.patch create mode 100644 0053-prevent-the-parent-dir-from-being-bind-mounted-to-th.patch create mode 100644 0054-2308-Remove-unused-header-file.patch create mode 100644 0055-verify-the-mount-dir-first-and-then-create-tmpdir.patch create mode 100644 0056-2300-Maintaining-a-uniform-code-style.patch create mode 100644 0057-2312-Add-Huawei-Cloud-CodeArts-compilation-script.patch create mode 100644 0058-bugfix-del-redundant-code.patch create mode 100644 0059-improve-code-of-pull.patch create mode 100644 0060-remove-var-in-coverage-and-fix-build-test-remove.patch create mode 100644 0061-2320-improve-CI-test.patch create mode 100644 0062-verify-name-and-digest-consistency.patch create mode 100644 0063-code-improve-for-oci_rmi.patch create mode 100644 0064-bugfix-for-resort_image_names.patch create mode 100644 0065-fix-stopp-removes-cont-error-remove-inspect-error-lo.patch create mode 100644 0066-2313-use-lxc-5.X-in-CI-testcase.patch create mode 100644 0067-2329-modify-mount-dev-directory-for-lxc-5.X.patch create mode 100644 0068-add-cri-1.29-api-change-docs.patch create mode 100644 0069-add-exec-workdir-support-for-oci-runtime.patch create mode 100644 0070-add-testcases-for-exec-workdir.patch create mode 100644 0071-iSulad-restart-isuald-when-upgrade-active-isulad.patch create mode 100644 iSulad.spec create mode 100644 sources diff --git a/.gitignore b/.gitignore index e69de29..0f035f6 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1 @@ +/v2.1.4.tar.gz diff --git a/0001-sandbox-del-m_containers-and-m_containersMutex.patch b/0001-sandbox-del-m_containers-and-m_containersMutex.patch new file mode 100644 index 0000000..84c3455 --- /dev/null +++ b/0001-sandbox-del-m_containers-and-m_containersMutex.patch @@ -0,0 +1,347 @@ +From d1aa4166d8ce7f3db83ff1ffbd54b796943233b3 Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Tue, 24 Oct 2023 16:19:15 +0800 +Subject: [PATCH 01/14] sandbox:del m_containers and m_containersMutex + +--- + .../v1/v1_cri_container_manager_service.cc | 30 ----- + .../cri/v1/v1_cri_container_manager_service.h | 1 - + .../v1/v1_cri_pod_sandbox_manager_service.cc | 103 +++++++++++++++--- + .../v1/v1_cri_pod_sandbox_manager_service.h | 7 +- + src/daemon/sandbox/sandbox.cc | 31 ------ + src/daemon/sandbox/sandbox.h | 7 -- + 6 files changed, 95 insertions(+), 84 deletions(-) + +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 eb19cac6..70629591 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 +@@ -499,7 +499,6 @@ std::string ContainerManagerService::CreateContainer(const std::string &podSandb + } + + response_id = response->id; +- sandbox->AddContainer(response_id); + + cleanup: + free_container_create_request(request); +@@ -591,37 +590,8 @@ void ContainerManagerService::StopContainer(const std::string &containerID, int6 + CRIHelpers::StopContainer(m_cb, containerID, timeout, error); + } + +-// TODO: Consider to refactor the way we handle container list in sandbox. +-// This function might be removed after that. +-void ContainerManagerService::RemoveContainerIDFromSandbox(const std::string &containerID) +-{ +- std::string realContainerID; +- std::string podSandboxID; +- Errors error; +- +- CRIHelpersV1::GetContainerSandboxID(containerID, realContainerID, podSandboxID, error); +- if (error.NotEmpty()) { +- WARN("Failed to get sandbox id for container %s: %s", containerID.c_str(), error.GetCMessage()); +- return; +- } +- +- std::shared_ptr sandbox = sandbox::SandboxManager::GetInstance()->GetSandbox(podSandboxID); +- if (sandbox == nullptr) { +- ERROR("Failed to get sandbox instance: %s for creating container", podSandboxID.c_str()); +- error.Errorf("Failed to get sandbox instance: %s for creating container", podSandboxID.c_str()); +- return; +- } +- +- sandbox->RemoveContainer(realContainerID); +-} +- + void ContainerManagerService::RemoveContainer(const std::string &containerID, Errors &error) + { +- // TODO: Refactor after adding the ability to use sandbox manager for sandboxid query +- // This will remove container id from sandbox container_list first, +- // if the following operation failed, it could cause inconsistency. +- RemoveContainerIDFromSandbox(containerID); +- + CRIHelpers::RemoveContainer(m_cb, containerID, error); + if (error.NotEmpty()) { + WARN("Failed to remove container %s", containerID.c_str()); +diff --git a/src/daemon/entry/cri/v1/v1_cri_container_manager_service.h b/src/daemon/entry/cri/v1/v1_cri_container_manager_service.h +index 31449170..1d210416 100644 +--- a/src/daemon/entry/cri/v1/v1_cri_container_manager_service.h ++++ b/src/daemon/entry/cri/v1/v1_cri_container_manager_service.h +@@ -97,7 +97,6 @@ private: + void MakeContainerConfig(const runtime::v1::ContainerConfig &config, container_config *cConfig, + Errors &error); + void CreateContainerLogSymlink(const std::string &containerID, Errors &error); +- void RemoveContainerIDFromSandbox(const std::string &containerID); + void ListContainersFromGRPC(const runtime::v1::ContainerFilter *filter, container_list_request **request, + Errors &error); + void ListContainersToGRPC(container_list_response *response, +diff --git a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc +index 901ef231..2c802900 100644 +--- a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc ++++ b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc +@@ -452,20 +452,90 @@ auto PodSandboxManagerService::GetSandboxKey(const container_inspect *inspect_da + return std::string(inspect_data->network_settings->sandbox_key); + } + +-auto PodSandboxManagerService::StopAllContainersInSandbox(const std::vector &containers, +- Errors &error) -> bool ++auto PodSandboxManagerService::GetContainerListResponse(const std::string &readSandboxID, ++ std::vector &errors) -> std::unique_ptr> + { ++ int ret = 0; ++ container_list_request *list_request { nullptr }; ++ container_list_response *list_response { nullptr }; ++ ++ if (m_cb == nullptr || m_cb->container.list == nullptr) { ++ ERROR("Unimplemented callback"); ++ errors.push_back("Unimplemented callback"); ++ return nullptr; ++ } ++ ++ // list all containers to stop ++ auto list_request_wrapper = makeUniquePtrCStructWrapper(free_container_list_request); ++ if (list_request_wrapper == nullptr) { ++ ERROR("Out of memory"); ++ errors.push_back("Out of memory"); ++ return nullptr; ++ } ++ list_request = list_request_wrapper->get(); ++ list_request->all = true; ++ ++ list_request->filters = (defs_filters *)util_common_calloc_s(sizeof(defs_filters)); ++ if (list_request->filters == nullptr) { ++ ERROR("Out of memory"); ++ errors.push_back("Out of memory"); ++ return nullptr; ++ } ++ ++ // Add sandbox label ++ if (CRIHelpers::FiltersAddLabel(list_request->filters, CRIHelpers::Constants::SANDBOX_ID_LABEL_KEY, ++ readSandboxID) != 0) { ++ std::string tmp_errmsg = "Failed to add label in sandbox" + readSandboxID; ++ ERROR(tmp_errmsg.c_str()); ++ errors.push_back(tmp_errmsg); ++ return nullptr; ++ } ++ ++ ret = m_cb->container.list(list_request, &list_response); ++ auto list_response_wrapper = makeUniquePtrCStructWrapper(list_response, free_container_list_response); ++ if (list_response_wrapper == nullptr) { ++ ERROR("Failed to call list container callback"); ++ errors.push_back("Failed to call list container callback"); ++ return nullptr; ++ } ++ if (ret != 0) { ++ if (list_response != nullptr && list_response->errmsg != nullptr) { ++ ERROR(list_response->errmsg); ++ errors.push_back(list_response->errmsg); ++ } else { ++ ERROR("Failed to call list container callback"); ++ errors.push_back("Failed to call list container callback"); ++ } ++ return nullptr; ++ } ++ ++ return list_response_wrapper; ++} ++ ++auto PodSandboxManagerService::StopAllContainersInSandbox(const std::string &readSandboxID, ++ Errors &error) -> int ++{ ++ int ret = 0; ++ std::vector errors; ++ auto list_response_wrapper = GetContainerListResponse(readSandboxID, errors); ++ if (list_response_wrapper == nullptr) { ++ error.SetAggregate(errors); ++ return -1; ++ } ++ auto list_response = list_response_wrapper->get(); ++ + // Stop all containers in the sandbox. +- for (const auto &con : containers) { ++ for (size_t i = 0; i < list_response->containers_len; i++) { + Errors stopError; +- CRIHelpers::StopContainerHelper(m_cb, con, 0, stopError); ++ CRIHelpers::StopContainerHelper(m_cb, list_response->containers[i]->id, 0, stopError); + if (stopError.NotEmpty() && !CRIHelpers::IsContainerNotFoundError(stopError.GetMessage())) { +- ERROR("Error stop container: %s: %s", con.c_str(), stopError.GetCMessage()); ++ ERROR("Error stop container: %s: %s", list_response->containers[i]->id, stopError.GetCMessage()); + error.SetError(stopError.GetMessage()); +- return false; ++ return -1; + } + } +- return true; ++ ++ return ret; + } + + auto PodSandboxManagerService::GetNetworkReady(const std::string &podSandboxID, Errors &error) -> bool +@@ -508,7 +578,7 @@ void PodSandboxManagerService::StopPodSandbox(const std::string &podSandboxID, E + // Stop all containers inside the sandbox. This terminates the container forcibly, + // and container may still be created, so production should not rely on this behavior. + // TODO: according to the state(stopping and removal) in sandbox to avoid future container creation. +- if (!StopAllContainersInSandbox(sandbox->GetContainers(), error)) { ++ if (StopAllContainersInSandbox(sandbox->GetId(), error) != 0) { + return; + } + +@@ -524,15 +594,22 @@ void PodSandboxManagerService::StopPodSandbox(const std::string &podSandboxID, E + sandbox->Stop(sandbox::DEFAULT_STOP_TIMEOUT, error); + } + +-void PodSandboxManagerService::RemoveAllContainersInSandbox(const std::vector &containers, ++void PodSandboxManagerService::RemoveAllContainersInSandbox(const std::string &readSandboxID, + std::vector &errors) + { ++ auto list_response_wrapper = GetContainerListResponse(readSandboxID, errors); ++ if (list_response_wrapper == nullptr) { ++ return; ++ } ++ ++ auto list_response = list_response_wrapper->get(); ++ + // Remove all containers in the sandbox. +- for (const auto &con : containers) { ++ for (size_t i = 0; i < list_response->containers_len; i++) { + Errors rmError; +- CRIHelpers::RemoveContainerHelper(m_cb, con, rmError); ++ CRIHelpers::RemoveContainerHelper(m_cb, list_response->containers[i]->id, rmError); + if (rmError.NotEmpty() && !CRIHelpers::IsContainerNotFoundError(rmError.GetMessage())) { +- ERROR("Error remove container: %s: %s", con.c_str(), rmError.GetCMessage()); ++ ERROR("Error remove container: %s: %s", list_response->containers[i]->id, rmError.GetCMessage()); + errors.push_back(rmError.GetMessage()); + } + } +@@ -598,7 +675,7 @@ void PodSandboxManagerService::RemovePodSandbox(const std::string &podSandboxID, + // Remove all containers inside the sandbox. + // container may still be created, so production should not rely on this behavior. + // TODO: according to the state(stopping and removal) in sandbox to avoid future container creation. +- RemoveAllContainersInSandbox(sandbox->GetContainers(), errors); ++ RemoveAllContainersInSandbox(sandbox->GetId(), errors); + if (errors.size() != 0) { + error.SetAggregate(errors); + return; +diff --git a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.h b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.h +index 48a7cf7f..2bd28007 100644 +--- a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.h ++++ b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.h +@@ -32,6 +32,7 @@ + #include "cgroup.h" + #include "sandbox.h" + #include "v1_cri_container_manager_service.h" ++#include "cstruct_wrapper.h" + + namespace CRIV1 { + class PodSandboxManagerService { +@@ -89,9 +90,11 @@ private: + Errors &error); + void ClearCniNetwork(const std::shared_ptr sandbox, Errors &error); + void StopContainerHelper(const std::string &containerID, Errors &error); +- auto StopAllContainersInSandbox(const std::vector &containers, Errors &error) -> bool; ++ auto GetContainerListResponse(const std::string &readSandboxID, ++ std::vector &errors) -> std::unique_ptr>; ++ auto StopAllContainersInSandbox(const std::string &readSandboxID, Errors &error) -> int; + auto GetNetworkReady(const std::string &podSandboxID, Errors &error) -> bool; +- void RemoveAllContainersInSandbox(const std::vector &containers, std::vector &errors); ++ void RemoveAllContainersInSandbox(const std::string &readSandboxID, std::vector &errors); + void ClearNetworkReady(const std::string &podSandboxID); + auto SharesHostNetwork(const container_inspect *inspect) -> runtime::v1::NamespaceMode; + auto SharesHostPid(const container_inspect *inspect) -> runtime::v1::NamespaceMode; +diff --git a/src/daemon/sandbox/sandbox.cc b/src/daemon/sandbox/sandbox.cc +index ece28f4d..c8fd30be 100644 +--- a/src/daemon/sandbox/sandbox.cc ++++ b/src/daemon/sandbox/sandbox.cc +@@ -135,12 +135,6 @@ auto Sandbox::GetRuntimeHandle() const -> const std::string & + return m_runtimeInfo.runtimeHandler; + } + +-auto Sandbox::GetContainers() -> std::vector +-{ +- ReadGuard lock(m_containersMutex); +- return m_containers; +-} +- + auto Sandbox::GetSandboxConfig() const -> const runtime::v1::PodSandboxConfig & + { + return *m_sandboxConfig; +@@ -409,27 +403,6 @@ void Sandbox::RemoveLabels(const std::string &key) + m_sandboxConfig->mutable_labels()->erase(key); + } + +-void Sandbox::AddContainer(const std::string &id) +-{ +- WriteGuard lock(m_containersMutex); +- m_containers.push_back(id); +-} +- +-void Sandbox::SetConatiners(const std::vector &cons) +-{ +- WriteGuard lock(m_containersMutex); +- m_containers = cons; +-} +- +-void Sandbox::RemoveContainer(const std::string &id) +-{ +- WriteGuard lock(m_containersMutex); +- auto it = std::find(m_containers.begin(), m_containers.end(), id); +- if (it != m_containers.end()) { +- m_containers.erase(it); +- } +-} +- + void Sandbox::UpdateNetworkSettings(const std::string &settingsJson, Errors &error) + { + if (settingsJson.length() == 0) { +@@ -1009,8 +982,6 @@ auto Sandbox::LoadMetadata(Errors &error) -> bool + m_networkReady = metadata->get()->network_ready; + m_taskAddress = std::string(metadata->get()->task_address); + m_netNsPath = std::string(metadata->get()->net_ns_path); +- Transform::CharArrayToStringVector((const char **)metadata->get()->containers, +- util_array_len((const char **)metadata->get()->containers), m_containers); + + ret = google::protobuf::util::JsonStringToMessage(metadata->get()->sandbox_config_json, &config).ok(); + if (!ret) { +@@ -1120,8 +1091,6 @@ void Sandbox::FillSandboxMetadata(sandbox_metadata* metadata, Errors &error) + metadata->task_address = util_strdup_s(m_taskAddress.c_str()); + metadata->net_ns_path = util_strdup_s(m_netNsPath.c_str()); + +- metadata->containers = Transform::StringVectorToCharArray(m_containers); +- + google::protobuf::util::MessageToJsonString(*m_sandboxConfig.get(), &jsonStr); + if (jsonStr.length() == 0) { + error.Errorf("Failed to get sandbox config json for sandbox: '%s'", m_id.c_str()); +diff --git a/src/daemon/sandbox/sandbox.h b/src/daemon/sandbox/sandbox.h +index 13ee4958..20a8e338 100644 +--- a/src/daemon/sandbox/sandbox.h ++++ b/src/daemon/sandbox/sandbox.h +@@ -104,7 +104,6 @@ public: + auto GetCreatedAt() -> uint64_t; + auto GetPid() -> uint32_t; + auto GetTaskAddress() const -> const std::string &; +- auto GetContainers() -> std::vector; + auto GetImage() -> const std::string &; + void SetNetMode(const std::string &mode); + void SetController(std::shared_ptr controller); +@@ -112,9 +111,6 @@ public: + void RemoveAnnotations(const std::string &key); + void AddLabels(const std::string &key, const std::string &value); + void RemoveLabels(const std::string &key); +- void AddContainer(const std::string &id); +- void SetConatiners(const std::vector &cons); +- void RemoveContainer(const std::string &id); + void UpdateNetworkSettings(const std::string &settingsJson, Errors &error); + auto UpdateStatsInfo(const StatsInfo &info) -> StatsInfo; + void SetNetworkReady(bool ready); +@@ -203,9 +199,6 @@ private: + bool m_networkReady; + std::string m_networkSettings; + std::string m_image; +- // container id lists +- std::vector m_containers; +- RWMutex m_containersMutex; + // TOOD: m_sandboxConfig is a protobuf message, it can be converted to json string directly + // if save json string directly for sandbox recover, we need to consider hot + // upgrade between different CRI versions +-- +2.42.0 + diff --git a/0002-sandbox-adapt-UT-when-del-m_containers-and-m_contain.patch b/0002-sandbox-adapt-UT-when-del-m_containers-and-m_contain.patch new file mode 100644 index 0000000..97a3302 --- /dev/null +++ b/0002-sandbox-adapt-UT-when-del-m_containers-and-m_contain.patch @@ -0,0 +1,167 @@ +From 415d7dca6175136ca4c1c780f1e512fd363d01c4 Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Fri, 3 Nov 2023 14:27:45 +0800 +Subject: [PATCH 02/14] sandbox:adapt UT when del m_containers and + m_containersMutex + +--- + .../design/detailed/Sandbox/sandbox_design_zh.md | 16 +--------------- + test/mocks/sandbox_mock.cc | 11 ----------- + test/mocks/sandbox_mock.h | 4 ---- + test/sandbox/sandbox/sandbox_ut.cc | 14 -------------- + 4 files changed, 1 insertion(+), 44 deletions(-) + +diff --git a/docs/design/detailed/Sandbox/sandbox_design_zh.md b/docs/design/detailed/Sandbox/sandbox_design_zh.md +index 86acd70b..109094cb 100644 +--- a/docs/design/detailed/Sandbox/sandbox_design_zh.md ++++ b/docs/design/detailed/Sandbox/sandbox_design_zh.md +@@ -99,7 +99,6 @@ auto GetNetworkSettings() -> const std::string &; + auto GetCreatedAt() -> uint64_t; + auto GetPid() -> uint32_t; + auto GetTaskAddress() const -> const std::string &; +-auto GetContainers() -> std::vector; + + // 设置和更新sandbox的变量值 + void SetNetMode(const std::string &mode); +@@ -108,9 +107,6 @@ void AddAnnotations(const std::string &key, const std::string &value); + void RemoveAnnotations(const std::string &key); + void AddLabels(const std::string &key, const std::string &value); + void RemoveLabels(const std::string &key); +-void AddContainer(const std::string &id); +-void SetConatiners(const std::vector &cons); +-void RemoveContainer(const std::string &id); + void UpdateNetworkSettings(const std::string &settingsJson, Errors &error); + auto UpdateStatsInfo(const StatsInfo &info) -> StatsInfo; + void SetNetworkReady(bool ready); +@@ -252,16 +248,12 @@ public: + auto GetCreatedAt() -> uint64_t; + auto GetPid() -> uint32_t; + auto GetTaskAddress() const -> const std::string &; +- auto GetContainers() -> std::vector; + void SetNetMode(const std::string &mode); + void SetController(std::shared_ptr controller); + void AddAnnotations(const std::string &key, const std::string &value); + void RemoveAnnotations(const std::string &key); + void AddLabels(const std::string &key, const std::string &value); + void RemoveLabels(const std::string &key); +- void AddContainer(const std::string &id); +- void SetConatiners(const std::vector &cons); +- void RemoveContainer(const std::string &id); + void UpdateNetworkSettings(const std::string &settingsJson, Errors &error); + auto UpdateStatsInfo(const StatsInfo &info) -> StatsInfo; + void SetNetworkReady(bool ready); +@@ -347,9 +339,6 @@ private: + std::string m_networkMode; + bool m_networkReady; + std::string m_networkSettings; +- // container id lists +- std::vector m_containers; +- RWMutex m_containersMutex; + // TOOD: m_sandboxConfig is a protobuf message, it can be converted to json string directly + // if save json string directly for sandbox recover, we need to consider hot + // upgrade between different CRI versions +@@ -410,9 +399,7 @@ std::string m_netNsPath; + std::string m_networkMode; + bool m_networkReady; + std::string m_networkSettings; +-// container id lists +-std::vector m_containers; +-RWMutex m_containersMutex; ++ + // TOOD: m_sandboxConfig is a protobuf message, it can be converted to json string directly + // if save json string directly for sandbox recover, we need to consider hot + // upgrade between different CRI versions +@@ -430,7 +417,6 @@ std::set m_vsockPorts; + + 1. m_mutex: 保障并发sandbox的生命周期操作(start, stop, remove) + 2. m_stateMutex:保障并发对m_state,m_statsInfo,m_networkSettings的修改与读取 +-3. m_containersMutex:保障对m_containers的并发操作 + + ## 4.2 sandbox manage 模块 + +diff --git a/test/mocks/sandbox_mock.cc b/test/mocks/sandbox_mock.cc +index ab6c2d60..e5aefdda 100644 +--- a/test/mocks/sandbox_mock.cc ++++ b/test/mocks/sandbox_mock.cc +@@ -77,14 +77,6 @@ const std::string &Sandbox::GetRuntimeHandle() const + return defaultStr; + } + +-std::vector Sandbox::GetContainers() +-{ +- if (g_sandbox_mock != nullptr) { +- return g_sandbox_mock->GetContainers(); +- } +- return defaultVec; +-} +- + const runtime::v1::PodSandboxConfig & Sandbox::GetSandboxConfig() const + { + if (g_sandbox_mock != nullptr) { +@@ -154,9 +146,6 @@ void Sandbox::AddAnnotations(const std::string &key, const std::string &value) { + void Sandbox::RemoveAnnotations(const std::string &key) {} + void Sandbox::AddLabels(const std::string &key, const std::string &value) {} + void Sandbox::RemoveLabels(const std::string &key) {} +-void Sandbox::AddContainer(const std::string &id) {} +-void Sandbox::SetConatiners(const std::vector &cons) {} +-void Sandbox::RemoveContainer(const std::string &id) {} + void Sandbox::UpdateNetworkSettings(const std::string &settingsJson, Errors &error) {} + void Sandbox::PrepareSandboxDirs(Errors &error) {} + void Sandbox::CleanupSandboxDirs() {} +diff --git a/test/mocks/sandbox_mock.h b/test/mocks/sandbox_mock.h +index 6b46dca6..341042e9 100644 +--- a/test/mocks/sandbox_mock.h ++++ b/test/mocks/sandbox_mock.h +@@ -31,7 +31,6 @@ public: + MOCK_METHOD0(GetName, const std::string & ()); + MOCK_METHOD0(GetSandboxer, const std::string & ()); + MOCK_METHOD0(GetRuntimeHandle, const std::string & ()); +- MOCK_METHOD0(GetContainers, std::vector()); + MOCK_METHOD0(GetSandboxConfig, const runtime::v1::PodSandboxConfig &()); + MOCK_METHOD0(GetMutableSandboxConfig, std::shared_ptr()); + MOCK_METHOD0(GetRootDir, const std::string & ()); +@@ -46,9 +45,6 @@ public: + MOCK_METHOD1(RemoveAnnotations, void(const std::string &key)); + MOCK_METHOD2(AddLabels, void(const std::string &key, const std::string &value)); + MOCK_METHOD1(RemoveLabels, void(const std::string &key)); +- MOCK_METHOD1(AddContainer, void(const std::string &id)); +- MOCK_METHOD1(SetConatiners, void(const std::vector &cons)); +- MOCK_METHOD1(RemoveContainer, void(const std::string &id)); + MOCK_METHOD2(UpdateNetworkSettings, void(const std::string &settingsJson, Errors &error)); + MOCK_METHOD1(UpdateStatsInfo, StatsInfo(const StatsInfo &info)); + MOCK_METHOD1(SetNetworkReady, void(bool ready)); +diff --git a/test/sandbox/sandbox/sandbox_ut.cc b/test/sandbox/sandbox/sandbox_ut.cc +index 494fb543..dd84d8fb 100644 +--- a/test/sandbox/sandbox/sandbox_ut.cc ++++ b/test/sandbox/sandbox/sandbox_ut.cc +@@ -49,7 +49,6 @@ TEST_F(SandboxTest, TestDefaultGetters) + ASSERT_STREQ(sandbox->GetRuntime().c_str(), info.runtime.c_str()); + ASSERT_STREQ(sandbox->GetSandboxer().c_str(), info.sandboxer.c_str()); + ASSERT_STREQ(sandbox->GetRuntimeHandle().c_str(), info.runtimeHandler.c_str()); +- ASSERT_EQ(sandbox->GetContainers().size(), 0); + ASSERT_STREQ(sandbox->GetRootDir().c_str(), sandbox_rootdir.c_str()); + ASSERT_STREQ(sandbox->GetStateDir().c_str(), sandbox_statedir.c_str()); + ASSERT_STREQ(sandbox->GetResolvPath().c_str(), (sandbox_rootdir + "/resolv.conf").c_str()); +@@ -85,19 +84,6 @@ TEST_F(SandboxTest, TestGettersAndSetters) + sandbox->RemoveLabels("key"); + EXPECT_TRUE(sandbox->GetSandboxConfig().labels().empty()); + +- std::string containerId = "container_id"; +- sandbox->AddContainer(containerId); +- auto Mycontainers = sandbox->GetContainers(); +- auto it = std::find(Mycontainers.begin(), Mycontainers.end(), containerId); +- EXPECT_NE(Mycontainers.end(), it); +- +- sandbox->RemoveContainer(containerId); +- EXPECT_EQ(sandbox->GetContainers().size(), 0); +- +- std::vector containers = {"container1", "container2"}; +- sandbox->SetConatiners(containers); +- EXPECT_EQ(sandbox->GetContainers(), containers); +- + StatsInfo statsInfo = {1234, 100}; + sandbox->UpdateStatsInfo(statsInfo); + EXPECT_EQ(sandbox->GetStatsInfo().timestamp, statsInfo.timestamp); +-- +2.42.0 + diff --git a/0003-Add-Readonly-Masked-Path-and-RunAsGroup-support-for-.patch b/0003-Add-Readonly-Masked-Path-and-RunAsGroup-support-for-.patch new file mode 100644 index 0000000..072a5e5 --- /dev/null +++ b/0003-Add-Readonly-Masked-Path-and-RunAsGroup-support-for-.patch @@ -0,0 +1,642 @@ +From c1eb46b00ea65fc5601f0d843bc485d087f687e0 Mon Sep 17 00:00:00 2001 +From: jikai +Date: Mon, 6 Nov 2023 17:31:58 +0800 +Subject: [PATCH 03/14] Add Readonly/Masked Path and RunAsGroup support for cri + +Signed-off-by: jikai +--- + .../common/cri/v1/v1_cri_security_context.cc | 111 ++++++++++++++++-- + .../v1/v1_cri_container_manager_service.cc | 16 ++- + .../entry/cri/v1alpha/cri_security_context.cc | 110 +++++++++++++++-- + src/daemon/modules/spec/specs.c | 74 +++++++++++- + src/daemon/modules/spec/specs_extend.c | 17 ++- + src/daemon/modules/spec/specs_security.c | 19 +-- + 6 files changed, 294 insertions(+), 53 deletions(-) + +diff --git a/src/daemon/common/cri/v1/v1_cri_security_context.cc b/src/daemon/common/cri/v1/v1_cri_security_context.cc +index f6441f42..930710e0 100644 +--- a/src/daemon/common/cri/v1/v1_cri_security_context.cc ++++ b/src/daemon/common/cri/v1/v1_cri_security_context.cc +@@ -19,15 +19,28 @@ + #include + + namespace CRISecurityV1 { +-static void ModifyContainerConfig(const runtime::v1::LinuxContainerSecurityContext &sc, container_config *config) ++static void ModifyContainerConfig(const runtime::v1::LinuxContainerSecurityContext &sc, container_config *config, Errors &error) + { ++ // none -> ""; username -> username; username, uid -> username; username, uid, gid -> username:gid; ++ // username, gid -> username:gid; uid -> uid; uid, gid -> uid:gid; gid -> error ++ std::string user; + if (sc.has_run_as_user()) { +- free(config->user); +- config->user = util_strdup_s(std::to_string(sc.run_as_user().value()).c_str()); ++ user = std::to_string(sc.run_as_user().value()); + } + if (!sc.run_as_username().empty()) { ++ user = sc.run_as_username(); ++ } ++ if (sc.has_run_as_group()) { ++ if (user.empty()) { ++ ERROR("Invalid security context: runAsGroup without runAsUser or runAsUsername"); ++ error.SetError("Invalid security context: runAsGroup without runAsUser or runAsUsername"); ++ return; ++ } ++ user += ":" + std::to_string(sc.run_as_group().value()); ++ } ++ if (!user.empty()) { + free(config->user); +- config->user = util_strdup_s(sc.run_as_username().c_str()); ++ config->user = util_strdup_s(user.c_str()); + } + } + +@@ -42,6 +55,7 @@ static void ModifyHostConfigCapabilities(const runtime::v1::LinuxContainerSecuri + if (!capAdd.empty()) { + hostConfig->cap_add = (char **)util_smart_calloc_s(sizeof(char *), capAdd.size()); + if (hostConfig->cap_add == nullptr) { ++ ERROR("Out of memory"); + error.SetError("Out of memory"); + return; + } +@@ -54,6 +68,7 @@ static void ModifyHostConfigCapabilities(const runtime::v1::LinuxContainerSecuri + if (!capDrop.empty()) { + hostConfig->cap_drop = (char **)util_smart_calloc_s(sizeof(char *), capDrop.size()); + if (hostConfig->cap_drop == nullptr) { ++ ERROR("Out of memory"); + error.SetError("Out of memory"); + return; + } +@@ -74,7 +89,8 @@ static void ModifyHostConfigNoNewPrivs(const runtime::v1::LinuxContainerSecurity + } + + if (hostConfig->security_opt_len > (SIZE_MAX / sizeof(char *)) - 1) { +- error.Errorf("Out of memory"); ++ ERROR("The size of security opts exceeds the limit"); ++ error.Errorf("The size of security opts exceeds the limit"); + return; + } + +@@ -82,6 +98,7 @@ static void ModifyHostConfigNoNewPrivs(const runtime::v1::LinuxContainerSecurity + size_t newSize = oldSize + sizeof(char *); + int ret = util_mem_realloc((void **)(&tmp_security_opt), newSize, (void *)hostConfig->security_opt, oldSize); + if (ret != 0) { ++ ERROR("Out of memory"); + error.Errorf("Out of memory"); + return; + } +@@ -98,12 +115,9 @@ static void ModifyHostConfigscSupplementalGroups(const runtime::v1::LinuxContain + + const google::protobuf::RepeatedField &groups = sc.supplemental_groups(); + if (!groups.empty()) { +- if (static_cast(groups.size()) > SIZE_MAX / sizeof(char *)) { +- error.SetError("Invalid group size"); +- return; +- } +- hostConfig->group_add = (char **)util_common_calloc_s(sizeof(char *) * groups.size()); ++ hostConfig->group_add = (char **)util_smart_calloc_s(sizeof(char *), groups.size()); + if (hostConfig->group_add == nullptr) { ++ ERROR("Out of memory"); + error.SetError("Out of memory"); + return; + } +@@ -114,6 +128,64 @@ static void ModifyHostConfigscSupplementalGroups(const runtime::v1::LinuxContain + } + } + ++static void ApplyMaskedPathsToHostConfig(const runtime::v1::LinuxContainerSecurityContext &sc, host_config *hostConfig, ++ Errors &error) ++{ ++ if (sc.masked_paths_size() <= 0) { ++ return; ++ } ++ ++ if (hostConfig->masked_paths_len > ((SIZE_MAX / sizeof(char *)) - sc.masked_paths_size())) { ++ ERROR("The size of masked paths exceeds the limit"); ++ error.Errorf("The size of masked paths exceeds the limit"); ++ return; ++ } ++ ++ char **tmp_masked_paths {nullptr}; ++ size_t oldSize = hostConfig->masked_paths_len * sizeof(char *); ++ size_t newSize = oldSize + sc.masked_paths_size() * sizeof(char *); ++ int ret = util_mem_realloc((void **)&tmp_masked_paths, newSize, (void *)hostConfig->masked_paths, oldSize); ++ if (ret != 0) { ++ ERROR("Out of memory"); ++ error.Errorf("Out of memory"); ++ return; ++ } ++ ++ hostConfig->masked_paths = tmp_masked_paths; ++ for (int i = 0; i < sc.masked_paths_size(); ++i) { ++ hostConfig->masked_paths[hostConfig->masked_paths_len++] = util_strdup_s(sc.masked_paths(i).c_str()); ++ } ++} ++ ++static void ApplyReadonlyPathsToHostConfig(const runtime::v1::LinuxContainerSecurityContext &sc, host_config *hostConfig, ++ Errors &error) ++{ ++ if (sc.readonly_paths_size() <= 0) { ++ return; ++ } ++ ++ if (hostConfig->readonly_paths_len > ((SIZE_MAX / sizeof(char *)) - sc.readonly_paths_size())) { ++ ERROR("The size of readonly paths exceeds the limit"); ++ error.Errorf("The size of readonly paths exceeds the limit"); ++ return; ++ } ++ ++ char **tmp_readonly_paths {nullptr}; ++ size_t oldSize = hostConfig->readonly_paths_len * sizeof(char *); ++ size_t newSize = oldSize + sc.readonly_paths_size() * sizeof(char *); ++ int ret = util_mem_realloc((void **)&tmp_readonly_paths, newSize, (void *)hostConfig->readonly_paths, oldSize); ++ if (ret != 0) { ++ ERROR("Out of memory"); ++ error.Errorf("Out of memory"); ++ return; ++ } ++ ++ hostConfig->readonly_paths = tmp_readonly_paths; ++ for (int i = 0; i < sc.readonly_paths_size(); ++i) { ++ hostConfig->readonly_paths[hostConfig->readonly_paths_len++] = util_strdup_s(sc.readonly_paths(i).c_str()); ++ } ++} ++ + static void ModifyHostConfig(const runtime::v1::LinuxContainerSecurityContext &sc, host_config *hostConfig, + Errors &error) + { +@@ -123,6 +195,8 @@ static void ModifyHostConfig(const runtime::v1::LinuxContainerSecurityContext &s + ModifyHostConfigCapabilities(sc, hostConfig, error); + ModifyHostConfigNoNewPrivs(sc, hostConfig, error); + ModifyHostConfigscSupplementalGroups(sc, hostConfig, error); ++ ApplyMaskedPathsToHostConfig(sc, hostConfig, error); ++ ApplyReadonlyPathsToHostConfig(sc, hostConfig, error); + } + + static void ModifyContainerNamespaceOptions(const runtime::v1::NamespaceOption &nsOpts, +@@ -196,11 +270,18 @@ void ApplySandboxSecurityContext(const runtime::v1::LinuxPodSandboxConfig &lc, c + *sc->mutable_supplemental_groups() = old.supplemental_groups(); + sc->set_readonly_rootfs(old.readonly_rootfs()); + } +- ModifyContainerConfig(*sc, config); ++ ModifyContainerConfig(*sc, config, error); ++ if (error.NotEmpty()) { ++ ERROR("Failed to modify container config for sandbox"); ++ return; ++ } ++ + ModifyHostConfig(*sc, hc, error); + if (error.NotEmpty()) { ++ ERROR("Failed to modify host config for sandbox"); + return; + } ++ + ModifySandboxNamespaceOptions(sc->namespace_options(), hc); + } + +@@ -209,9 +290,15 @@ void ApplyContainerSecurityContext(const runtime::v1::LinuxContainerConfig &lc, + { + if (lc.has_security_context()) { + const runtime::v1::LinuxContainerSecurityContext &sc = lc.security_context(); +- ModifyContainerConfig(sc, config); ++ ModifyContainerConfig(sc, config, error); ++ if (error.NotEmpty()) { ++ ERROR("Failed to modify container config for container"); ++ return; ++ } ++ + ModifyHostConfig(sc, hc, error); + if (error.NotEmpty()) { ++ ERROR("Failed to modify host config for container"); + return; + } + } +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 70629591..1f20d2d2 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 +@@ -128,8 +128,22 @@ void ContainerManagerService::DoUsePodLevelSELinuxConfig(const runtime::v1::Cont + return; + } + ++ const char securityOptSep = '='; ++ + const runtime::v1::LinuxSandboxSecurityContext &context = config.linux().security_context(); +- CRIHelpersV1::ApplySandboxSecurityContextToHostConfig(context, hostconfig, error); ++ std::vector selinuxOpts = CRIHelpersV1::GetSELinuxLabelOpts(context.has_selinux_options(), ++ context.selinux_options(), securityOptSep, error); ++ if (error.NotEmpty()) { ++ ERROR("Failed to generate SELinuxLabel options for container %s", error.GetMessage().c_str()); ++ error.Errorf("Failed to generate SELinuxLabel options for container %s", error.GetMessage().c_str()); ++ return; ++ } ++ CRIHelpersV1::AddSecurityOptsToHostConfig(selinuxOpts, hostconfig, error); ++ if (error.NotEmpty()) { ++ ERROR("Failed to add securityOpts to hostconfig: %s", error.GetMessage().c_str()); ++ error.Errorf("Failed to add securityOpts to hostconfig: %s", error.GetMessage().c_str()); ++ return; ++ } + } + + auto ContainerManagerService::IsSELinuxLabelEmpty(const ::runtime::v1::SELinuxOption &selinuxOption) -> bool +diff --git a/src/daemon/entry/cri/v1alpha/cri_security_context.cc b/src/daemon/entry/cri/v1alpha/cri_security_context.cc +index 0535b438..57ec3a63 100644 +--- a/src/daemon/entry/cri/v1alpha/cri_security_context.cc ++++ b/src/daemon/entry/cri/v1alpha/cri_security_context.cc +@@ -20,15 +20,29 @@ + #include + + namespace CRISecurity { +-static void ModifyContainerConfig(const runtime::v1alpha2::LinuxContainerSecurityContext &sc, container_config *config) ++static void ModifyContainerConfig(const runtime::v1alpha2::LinuxContainerSecurityContext &sc, container_config *config, ++ Errors &error) + { ++ // none -> ""; username -> username; username, uid -> username; username, uid, gid -> username:gid; ++ // username, gid -> username:gid; uid -> uid; uid, gid -> uid:gid; gid -> error ++ std::string user; + if (sc.has_run_as_user()) { +- free(config->user); +- config->user = util_strdup_s(std::to_string(sc.run_as_user().value()).c_str()); ++ user = std::to_string(sc.run_as_user().value()); + } + if (!sc.run_as_username().empty()) { ++ user = sc.run_as_username(); ++ } ++ if (sc.has_run_as_group()) { ++ if (user.empty()) { ++ ERROR("Invalid security context: runAsGroup without runAsUser or runAsUsername"); ++ error.SetError("Invalid security context: runAsGroup without runAsUser or runAsUsername"); ++ return; ++ } ++ user += ":" + std::to_string(sc.run_as_group().value()); ++ } ++ if (!user.empty()) { + free(config->user); +- config->user = util_strdup_s(sc.run_as_username().c_str()); ++ config->user = util_strdup_s(user.c_str()); + } + } + +@@ -43,6 +57,7 @@ static void ModifyHostConfigCapabilities(const runtime::v1alpha2::LinuxContainer + if (!capAdd.empty()) { + hostConfig->cap_add = (char **)util_smart_calloc_s(sizeof(char *), capAdd.size()); + if (hostConfig->cap_add == nullptr) { ++ ERROR("Out of memory"); + error.SetError("Out of memory"); + return; + } +@@ -55,6 +70,7 @@ static void ModifyHostConfigCapabilities(const runtime::v1alpha2::LinuxContainer + if (!capDrop.empty()) { + hostConfig->cap_drop = (char **)util_smart_calloc_s(sizeof(char *), capDrop.size()); + if (hostConfig->cap_drop == nullptr) { ++ ERROR("Out of memory"); + error.SetError("Out of memory"); + return; + } +@@ -75,7 +91,8 @@ static void ModifyHostConfigNoNewPrivs(const runtime::v1alpha2::LinuxContainerSe + } + + if (hostConfig->security_opt_len > (SIZE_MAX / sizeof(char *)) - 1) { +- error.Errorf("Out of memory"); ++ ERROR("The size of security opts exceeds the limit"); ++ error.Errorf("The size of security opts exceeds the limit"); + return; + } + +@@ -83,6 +100,7 @@ static void ModifyHostConfigNoNewPrivs(const runtime::v1alpha2::LinuxContainerSe + size_t newSize = oldSize + sizeof(char *); + int ret = util_mem_realloc((void **)(&tmp_security_opt), newSize, (void *)hostConfig->security_opt, oldSize); + if (ret != 0) { ++ ERROR("Out of memory"); + error.Errorf("Out of memory"); + return; + } +@@ -99,12 +117,9 @@ static void ModifyHostConfigscSupplementalGroups(const runtime::v1alpha2::LinuxC + + const google::protobuf::RepeatedField &groups = sc.supplemental_groups(); + if (!groups.empty()) { +- if (static_cast(groups.size()) > SIZE_MAX / sizeof(char *)) { +- error.SetError("Invalid group size"); +- return; +- } +- hostConfig->group_add = (char **)util_common_calloc_s(sizeof(char *) * groups.size()); ++ hostConfig->group_add = (char **)util_smart_calloc_s(sizeof(char *), groups.size()); + if (hostConfig->group_add == nullptr) { ++ ERROR("Out of memory"); + error.SetError("Out of memory"); + return; + } +@@ -115,6 +130,64 @@ static void ModifyHostConfigscSupplementalGroups(const runtime::v1alpha2::LinuxC + } + } + ++static void ApplyMaskedPathsToHostConfig(const runtime::v1alpha2::LinuxContainerSecurityContext &sc, host_config *hostConfig, ++ Errors &error) ++{ ++ if (sc.masked_paths_size() <= 0) { ++ return; ++ } ++ ++ if (hostConfig->masked_paths_len > ((SIZE_MAX / sizeof(char *)) - sc.masked_paths_size())) { ++ ERROR("The size of masked paths exceeds the limit"); ++ error.Errorf("The size of masked paths exceeds the limit"); ++ return; ++ } ++ ++ char **tmp_masked_paths {nullptr}; ++ size_t oldSize = hostConfig->masked_paths_len * sizeof(char *); ++ size_t newSize = oldSize + sc.masked_paths_size() * sizeof(char *); ++ int ret = util_mem_realloc((void **)&tmp_masked_paths, newSize, (void *)hostConfig->masked_paths, oldSize); ++ if (ret != 0) { ++ ERROR("Out of memory"); ++ error.Errorf("Out of memory"); ++ return; ++ } ++ ++ hostConfig->masked_paths = tmp_masked_paths; ++ for (int i = 0; i < sc.masked_paths_size(); ++i) { ++ hostConfig->masked_paths[hostConfig->masked_paths_len++] = util_strdup_s(sc.masked_paths(i).c_str()); ++ } ++} ++ ++static void ApplyReadonlyPathsToHostConfig(const runtime::v1alpha2::LinuxContainerSecurityContext &sc, host_config *hostConfig, ++ Errors &error) ++{ ++ if (sc.readonly_paths_size() <= 0) { ++ return; ++ } ++ ++ if (hostConfig->readonly_paths_len > ((SIZE_MAX / sizeof(char *)) - sc.readonly_paths_size())) { ++ ERROR("The size of readonly paths exceeds the limit"); ++ error.Errorf("The size of readonly paths exceeds the limit"); ++ return; ++ } ++ ++ char **tmp_readonly_paths {nullptr}; ++ size_t oldSize = hostConfig->readonly_paths_len * sizeof(char *); ++ size_t newSize = oldSize + sc.readonly_paths_size() * sizeof(char *); ++ int ret = util_mem_realloc((void **)&tmp_readonly_paths, newSize, (void *)hostConfig->readonly_paths, oldSize); ++ if (ret != 0) { ++ ERROR("Out of memory"); ++ error.Errorf("Out of memory"); ++ return; ++ } ++ ++ hostConfig->readonly_paths = tmp_readonly_paths; ++ for (int i = 0; i < sc.readonly_paths_size(); ++i) { ++ hostConfig->readonly_paths[hostConfig->readonly_paths_len++] = util_strdup_s(sc.readonly_paths(i).c_str()); ++ } ++} ++ + static void ModifyHostConfig(const runtime::v1alpha2::LinuxContainerSecurityContext &sc, host_config *hostConfig, + Errors &error) + { +@@ -124,6 +197,8 @@ static void ModifyHostConfig(const runtime::v1alpha2::LinuxContainerSecurityCont + ModifyHostConfigCapabilities(sc, hostConfig, error); + ModifyHostConfigNoNewPrivs(sc, hostConfig, error); + ModifyHostConfigscSupplementalGroups(sc, hostConfig, error); ++ ApplyMaskedPathsToHostConfig(sc, hostConfig, error); ++ ApplyReadonlyPathsToHostConfig(sc, hostConfig, error); + } + + static void ModifyContainerNamespaceOptions(const runtime::v1alpha2::NamespaceOption &nsOpts, +@@ -179,6 +254,7 @@ void ApplySandboxSecurityContext(const runtime::v1alpha2::LinuxPodSandboxConfig + std::unique_ptr sc( + new (std::nothrow) runtime::v1alpha2::LinuxContainerSecurityContext); + if (sc == nullptr) { ++ ERROR("Out of memory"); + error.SetError("Out of memory"); + return; + } +@@ -197,9 +273,14 @@ void ApplySandboxSecurityContext(const runtime::v1alpha2::LinuxPodSandboxConfig + *sc->mutable_supplemental_groups() = old.supplemental_groups(); + sc->set_readonly_rootfs(old.readonly_rootfs()); + } +- ModifyContainerConfig(*sc, config); ++ ModifyContainerConfig(*sc, config, error); ++ if (error.NotEmpty()) { ++ ERROR("Failed to modify container config for sandbox"); ++ return; ++ } + ModifyHostConfig(*sc, hc, error); + if (error.NotEmpty()) { ++ ERROR("Failed to modify host config for sandbox"); + return; + } + ModifySandboxNamespaceOptions(sc->namespace_options(), hc); +@@ -210,9 +291,14 @@ void ApplyContainerSecurityContext(const runtime::v1alpha2::LinuxContainerConfig + { + if (lc.has_security_context()) { + const runtime::v1alpha2::LinuxContainerSecurityContext &sc = lc.security_context(); +- ModifyContainerConfig(sc, config); ++ ModifyContainerConfig(sc, config, error); ++ if (error.NotEmpty()) { ++ ERROR("Failed to modify container config for container"); ++ return; ++ } + ModifyHostConfig(sc, hc, error); + if (error.NotEmpty()) { ++ ERROR("Failed to modify host config for container"); + return; + } + } +diff --git a/src/daemon/modules/spec/specs.c b/src/daemon/modules/spec/specs.c +index a7751d1b..95346603 100644 +--- a/src/daemon/modules/spec/specs.c ++++ b/src/daemon/modules/spec/specs.c +@@ -2133,6 +2133,58 @@ static int generate_security_opt(host_config *hc) + } + #endif + ++static int merge_paths(char ***dest_paths, size_t *dest_paths_len, char **src_paths, size_t src_paths_len) ++{ ++ if (dest_paths == NULL || dest_paths_len == NULL) { ++ ERROR("Invalid args"); ++ return -1; ++ } ++ ++ if (src_paths_len > SIZE_MAX / sizeof(char *) || ++ *dest_paths_len > ((SIZE_MAX / sizeof(char *)) - src_paths_len)) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ ++ size_t i; ++ char **tmp_paths = NULL; ++ size_t old_size = *dest_paths_len * sizeof(char *); ++ size_t new_size = old_size + src_paths_len * sizeof(char *); ++ int ret = util_mem_realloc((void **)&tmp_paths, new_size, ++ (void *)*dest_paths, old_size); ++ if (ret != 0) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ ++ *dest_paths = tmp_paths; ++ for (i = 0; i < src_paths_len; i++) { ++ (*dest_paths)[(*dest_paths_len)++] = util_strdup_s(src_paths[i]); ++ } ++ ++ return 0; ++} ++ ++static int merge_masked_paths(oci_runtime_spec *oci_spec, char **masked_paths, size_t masked_paths_len) ++{ ++ if (masked_paths == NULL || masked_paths_len == 0) { ++ return 0; ++ } ++ ++ return merge_paths(&oci_spec->linux->masked_paths, &oci_spec->linux->masked_paths_len, ++ masked_paths, masked_paths_len); ++} ++ ++static int merge_readonly_paths(oci_runtime_spec *oci_spec, char **readonly_paths, size_t readonly_paths_len) ++{ ++ if (readonly_paths == NULL || readonly_paths_len == 0) { ++ return 0; ++ } ++ ++ return merge_paths(&oci_spec->linux->readonly_paths, &oci_spec->linux->readonly_paths_len, ++ readonly_paths, readonly_paths_len); ++} ++ + static int merge_security_conf(oci_runtime_spec *oci_spec, host_config *host_spec, + container_config_v2_common_config *v2_spec) + { +@@ -2180,6 +2232,18 @@ static int merge_security_conf(oci_runtime_spec *oci_spec, host_config *host_spe + } + #endif + ++ ret = merge_masked_paths(oci_spec, host_spec->masked_paths, host_spec->masked_paths_len); ++ if (ret != 0) { ++ ERROR("Failed to merge masked paths"); ++ goto out; ++ } ++ ++ ret = merge_readonly_paths(oci_spec, host_spec->readonly_paths, host_spec->readonly_paths_len); ++ if (ret != 0) { ++ ERROR("Failed to merge readonly paths"); ++ goto out; ++ } ++ + out: + return ret; + } +@@ -2205,11 +2269,6 @@ static int merge_oci_cgroups_path(const char *id, oci_runtime_spec *oci_spec, co + return -1; + } + +- if (make_sure_oci_spec_linux(oci_spec) != 0) { +- ERROR("Failed to make oci spec linux"); +- return -1; +- } +- + free(oci_spec->linux->cgroups_path); + oci_spec->linux->cgroups_path = merge_container_cgroups_path(id, host_spec); + +@@ -2228,6 +2287,11 @@ int merge_all_specs(host_config *host_spec, const char *real_rootfs, container_c + char *userns_remap = conf_get_isulad_userns_remap(); + #endif + ++ if (make_sure_oci_spec_linux(oci_spec) != 0) { ++ ERROR("Failed to make oci spec linux"); ++ return -1; ++ } ++ + ret = merge_root(oci_spec, real_rootfs, host_spec); + if (ret != 0) { + ERROR("Failed to merge root"); +diff --git a/src/daemon/modules/spec/specs_extend.c b/src/daemon/modules/spec/specs_extend.c +index 5ede7936..199cba54 100644 +--- a/src/daemon/modules/spec/specs_extend.c ++++ b/src/daemon/modules/spec/specs_extend.c +@@ -136,28 +136,21 @@ static int make_linux_uid_gid_mappings(oci_runtime_spec *container, unsigned int + unsigned int size) + { + int ret = 0; +- +- ret = make_sure_oci_spec_linux(container); +- if (ret < 0) { +- goto out; +- } +- + if (container->linux->uid_mappings == NULL) { + ret = make_one_id_mapping(&(container->linux->uid_mappings), host_uid, size); + if (ret < 0) { +- goto out; ++ return ret; + } + container->linux->uid_mappings_len++; + } + if (container->linux->gid_mappings == NULL) { + ret = make_one_id_mapping(&(container->linux->gid_mappings), host_gid, size); + if (ret < 0) { +- goto out; ++ return ret; + } + container->linux->gid_mappings_len++; + } + +-out: + return ret; + } + +@@ -180,6 +173,12 @@ int make_userns_remap(oci_runtime_spec *container, const char *user_remap) + if (host_uid == 0 && host_gid == 0) { + return 0; + } ++ ++ if (make_sure_oci_spec_linux(container) != 0) { ++ ERROR("Failed to make oci spce linux"); ++ return -1; ++ } ++ + ret = make_linux_uid_gid_mappings(container, host_uid, host_gid, size); + if (ret) { + ERROR("Make linux uid and gid mappings failed"); +diff --git a/src/daemon/modules/spec/specs_security.c b/src/daemon/modules/spec/specs_security.c +index 08db8d0d..e78cc744 100644 +--- a/src/daemon/modules/spec/specs_security.c ++++ b/src/daemon/modules/spec/specs_security.c +@@ -879,13 +879,6 @@ int merge_caps(oci_runtime_spec *oci_spec, const char **adds, size_t adds_len, c + + static int make_sure_oci_spec_linux_sysctl(oci_runtime_spec *oci_spec) + { +- int ret = 0; +- +- ret = make_sure_oci_spec_linux(oci_spec); +- if (ret < 0) { +- return -1; +- } +- + if (oci_spec->linux->sysctl == NULL) { + oci_spec->linux->sysctl = util_common_calloc_s(sizeof(json_map_string_string)); + if (oci_spec->linux->sysctl == NULL) { +@@ -904,6 +897,11 @@ int merge_sysctls(oci_runtime_spec *oci_spec, const json_map_string_string *sysc + return 0; + } + ++ ret = make_sure_oci_spec_linux(oci_spec); ++ if (ret < 0) { ++ return -1; ++ } ++ + ret = make_sure_oci_spec_linux_sysctl(oci_spec); + if (ret < 0) { + goto out; +@@ -1004,13 +1002,6 @@ static void free_adds_cap_for_system_container(char **adds, size_t adds_len) + + static int make_sure_oci_spec_linux_seccomp(oci_runtime_spec *oci_spec) + { +- int ret = 0; +- +- ret = make_sure_oci_spec_linux(oci_spec); +- if (ret < 0) { +- return -1; +- } +- + if (oci_spec->linux->seccomp == NULL) { + oci_spec->linux->seccomp = util_common_calloc_s(sizeof(oci_runtime_config_linux_seccomp)); + if (oci_spec->linux->seccomp == NULL) { +-- +2.42.0 + diff --git a/0004-network-support-version-opt.patch b/0004-network-support-version-opt.patch new file mode 100644 index 0000000..db3a845 --- /dev/null +++ b/0004-network-support-version-opt.patch @@ -0,0 +1,482 @@ +From 7a2dd92a527c1f5ee79239d93b792dc9a9758e27 Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Tue, 7 Nov 2023 20:38:22 +0800 +Subject: [PATCH 04/14] network:support version opt + +--- + .../network/cni_operator/cni_operate.c | 16 +++ + .../network/cni_operator/cni_operate.h | 3 + + .../cni_operator/libcni/invoke/libcni_exec.c | 86 +++++++++++++- + .../cni_operator/libcni/invoke/libcni_exec.h | 2 + + .../libcni/invoke/libcni_result_parse.c | 29 +++++ + .../libcni/invoke/libcni_result_parse.h | 6 + + .../network/cni_operator/libcni/libcni_api.c | 106 ++++++++++++++++++ + .../network/cni_operator/libcni/libcni_api.h | 8 +- + .../cni_operator/libcni/libcni_result_type.c | 18 +++ + .../cni_operator/libcni/libcni_result_type.h | 12 ++ + .../modules/network/native/adaptor_native.c | 3 +- + 11 files changed, 281 insertions(+), 8 deletions(-) + +diff --git a/src/daemon/modules/network/cni_operator/cni_operate.c b/src/daemon/modules/network/cni_operator/cni_operate.c +index 62249f18..6db6db51 100644 +--- a/src/daemon/modules/network/cni_operator/cni_operate.c ++++ b/src/daemon/modules/network/cni_operator/cni_operate.c +@@ -926,6 +926,22 @@ out: + return ret; + } + ++int version_network_plane(const struct cni_network_list_conf *list, ++ struct cni_version_info_list **result_version_list) ++{ ++ if (list == NULL || list->list == NULL) { ++ ERROR("Invalid input params"); ++ return -1; ++ } ++ ++ if (cni_version_network_list(list, result_version_list) != 0) { ++ ERROR("Version CNI network failed"); ++ return -1; ++ } ++ ++ return 0; ++} ++ + int detach_loopback(const char *id, const char *netns) + { + int ret = 0; +diff --git a/src/daemon/modules/network/cni_operator/cni_operate.h b/src/daemon/modules/network/cni_operator/cni_operate.h +index 150c1154..7750ff00 100644 +--- a/src/daemon/modules/network/cni_operator/cni_operate.h ++++ b/src/daemon/modules/network/cni_operator/cni_operate.h +@@ -61,6 +61,9 @@ int detach_network_plane(const struct cni_manager *manager, const struct cni_net + int check_network_plane(const struct cni_manager *manager, const struct cni_network_list_conf *list, + struct cni_opt_result **result); + ++int version_network_plane(const struct cni_network_list_conf *list, ++ struct cni_version_info_list **result_version_list); ++ + #ifdef __cplusplus + } + #endif +diff --git a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c +index c4bc81c0..4908565e 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c ++++ b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c +@@ -28,7 +28,7 @@ + #include + + #include +-#include ++#include + #include + #include + #include +@@ -183,10 +183,10 @@ static char *str_cni_exec_error(const cni_exec_error *e_err) + static char *cniversion_decode(const char *jsonstr) + { + __isula_auto_free parser_error err = NULL; +- cni_version *conf = NULL; ++ cni_version_info *conf = NULL; + char *result = NULL; + +- conf = cni_version_parse_data(jsonstr, NULL, &err); ++ conf = cni_version_info_parse_data(jsonstr, NULL, &err); + if (conf == NULL) { + ERROR("decoding config \"%s\", failed: %s", jsonstr, err); + goto out; +@@ -198,7 +198,7 @@ static char *cniversion_decode(const char *jsonstr) + + result = util_strdup_s(conf->cni_version); + out: +- free_cni_version(conf); ++ free_cni_version_info(conf); + return result; + } + +@@ -466,6 +466,84 @@ out: + return ret; + } + ++static char *get_default_version_stdin(void) ++{ ++ char *stdin_str = NULL; ++ int ret; ++ ++ ret = asprintf(&stdin_str, "{\"cniVersion\":\"%s\"}", CURRENT_VERSION); ++ if (ret < 0) { ++ ERROR("parse cni version failed"); ++ } ++ return stdin_str; ++} ++ ++static int do_parse_version_info_stdout_str(int exec_ret, const cni_exec_error *e_err, ++ const char *stdout_str, cni_version_info **result_version) ++{ ++ __isula_auto_free char *err_msg = NULL; ++ struct parser_context ctx = { OPT_GEN_SIMPLIFY, 0 }; ++ __isula_auto_free parser_error perr = NULL; ++ ++ if (exec_ret != 0) { ++ err_msg = str_cni_exec_error(e_err); ++ ERROR("raw exec failed: %s", err_msg); ++ isulad_append_error_message("raw exec failed: %s. ", err_msg); ++ return -1; ++ } ++ ++ if (stdout_str == NULL || strlen(stdout_str) == 0) { ++ ERROR("Get empty version result"); ++ return -1; ++ } ++ free_cni_version_info(*result_version); ++ *result_version = cni_version_info_parse_data(stdout_str, &ctx, &perr); ++ if (*result_version == NULL) { ++ ERROR("parse cni result version failed: %s", perr); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int get_version_info(const char *plugin_path, cni_version_info **result_version) ++{ ++ __isula_auto_free char *err_msg = NULL; ++ char **envs = NULL; ++ __isula_auto_free char *stdout_str = NULL; ++ __isula_auto_free char *stdin_str = NULL; ++ cni_exec_error *e_err = NULL; ++ int ret = 0; ++ const struct cni_args cniargs = { ++ .command = "VERSION", ++ .netns = "dummy", ++ .ifname = "dummy", ++ .path = "dummy", ++ .container_id = "dummy" ++ }; ++ ++ stdin_str = get_default_version_stdin(); ++ if (stdin_str == NULL) { ++ return -1; ++ } ++ ++ envs = as_env(&cniargs); ++ if (envs == NULL) { ++ ERROR("create env failed"); ++ return -1; ++ } ++ ++ ret = raw_exec(plugin_path, stdin_str, envs, &stdout_str, &e_err); ++ DEBUG("Raw exec \"%s\" result: %d", plugin_path, ret); ++ DEBUG("Raw exec stdout: %s", stdout_str); ++ ret = do_parse_version_info_stdout_str(ret, e_err, stdout_str, result_version); ++ ++ util_free_array(envs); ++ free_cni_exec_error(e_err); ++ return ret; ++ ++} ++ + void free_cni_args(struct cni_args *cargs) + { + size_t i = 0; +diff --git a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.h b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.h +index 60b1c972..48d8d8b6 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.h ++++ b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.h +@@ -40,6 +40,8 @@ int exec_plugin_with_result(const char *plugin_path, const char *cni_net_conf_js + + int exec_plugin_without_result(const char *plugin_path, const char *cni_net_conf_json, const struct cni_args *cniargs); + ++int get_version_info(const char *plugin_path, cni_version_info **result_version); ++ + #ifdef __cplusplus + } + #endif +diff --git a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.c b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.c +index 164b2e29..aa4f75cf 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.c ++++ b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.c +@@ -741,3 +741,32 @@ struct cni_opt_result *new_result(const char *version, const char *jsonstr) + ERROR("unsupported CNI result version \"%s\"", version); + return NULL; + } ++ ++size_t get_curr_support_version_len(void) ++{ ++ return CURR_SUPPORT_VERSION_LEN; ++} ++ ++int get_support_version_pos(const char *version) ++{ ++ int i = 0; ++ if (version == NULL) { ++ return -1; ++ } ++ ++ for (i = CURR_SUPPORT_VERSION_LEN - 1; i >= 0; i--) { ++ if ((g_curr_support_versions[i] != NULL) && (strcmp(version, g_curr_support_versions[i]) == 0)) { ++ return i; ++ } ++ } ++ ++ return -1; ++} ++ ++const char *get_support_version_by_pos(size_t pos) ++{ ++ if (pos >= CURR_SUPPORT_VERSION_LEN) { ++ return NULL; ++ } ++ return g_curr_support_versions[pos]; ++} +\ No newline at end of file +diff --git a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.h b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.h +index 547bc915..438e1332 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.h ++++ b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.h +@@ -37,6 +37,12 @@ cni_result_curr *cni_result_curr_to_json_result(const struct cni_opt_result *src + + struct cni_opt_result *copy_result_from_current(const cni_result_curr *curr_result); + ++size_t get_curr_support_version_len(void); ++ ++int get_support_version_pos(const char *version); ++ ++const char *get_support_version_by_pos(size_t pos); ++ + #ifdef __cplusplus + } + #endif +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 781759e8..7f62df78 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/libcni_api.c ++++ b/src/daemon/modules/network/cni_operator/libcni/libcni_api.c +@@ -843,6 +843,112 @@ free_out: + return ret; + } + ++static int version_network(const char *plugin_name, cni_version_info **result_version) ++{ ++ int ret = 0; ++ __isula_auto_free char *plugin_path = NULL; ++ ++ if (plugin_name == NULL) { ++ ERROR("Empty plugin name"); ++ return -1; ++ } ++ ++ ret = find_plugin_in_path(plugin_name, (const char * const *)g_module_conf.bin_paths, ++ g_module_conf.bin_paths_len, &plugin_path); ++ if (ret != 0) { ++ ERROR("Failed to find plugin: \"%s\"", plugin_name); ++ isulad_append_error_message("Failed to find plugin: \"%s\". ", plugin_name); ++ return ret; ++ } ++ ++ // cni plugin calls should not take longer than 90 seconds ++ CALL_CHECK_TIMEOUT(90, ret = get_version_info(plugin_path, result_version)); ++ return ret; ++} ++ ++int cni_version_network_list(const struct cni_network_list_conf *list, ++ struct cni_version_info_list **result_version_list) ++{ ++ int ret = 0; ++ int i; ++ cni_version_info *tmp_result_version = NULL; ++ ++ if ((list == NULL) || (list->list == NULL) || (result_version_list == NULL)) { ++ ERROR("Empty arguments"); ++ return -1; ++ } ++ ++ *result_version_list = util_common_calloc_s(sizeof(struct cni_version_info_list)); ++ if (*result_version_list == NULL) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ (*result_version_list)->result_versions = util_smart_calloc_s(sizeof(cni_version_info *), list->list->plugins_len); ++ if ((*result_version_list)->result_versions == NULL) { ++ ERROR("Out of memory"); ++ ret = -1; ++ goto free_out; ++ } ++ ++ for (i = 0; i < list->list->plugins_len; i++) { ++ if (version_network(list->list->plugins[i]->type, &tmp_result_version) != 0) { ++ ret = -1; ++ ERROR("Run version plugin: %d failed", i); ++ goto free_out; ++ } ++ (*result_version_list)->result_versions[i] = tmp_result_version; ++ (*result_version_list)->result_versions_len += 1; ++ tmp_result_version = NULL; ++ } ++ ++ return ret; ++ ++free_out: ++ free_cni_version_info_list(*result_version_list); ++ *result_version_list = NULL; ++ return ret; ++} ++ ++/* get the latest CNI version supported by all plugins */ ++char *cni_get_plugins_supported_version(cni_net_conf_list *list) ++{ ++ // init to default version, if no found, just return default version ++ char *cni_version = util_strdup_s(CURRENT_VERSION); ++ int i, j, version_pos; ++ struct cni_version_info_list *result_version_list = NULL; ++ struct cni_network_list_conf network_list = { ++ .list = list, ++ }; ++ size_t curr_support_version_len = get_curr_support_version_len(); ++ __isula_auto_free size_t *plugin_version_count = util_smart_calloc_s(sizeof(size_t), curr_support_version_len); ++ if (plugin_version_count == NULL) { ++ return cni_version; ++ } ++ if (cni_version_network_list(&network_list, &result_version_list) != 0) { ++ return cni_version; ++ } ++ ++ // count plugin supported version ++ for (i = 0; i < result_version_list->result_versions_len; i++) { ++ for (j = result_version_list->result_versions[i]->supported_versions_len - 1; j >= 0 ; j--) { ++ version_pos = get_support_version_pos(result_version_list->result_versions[i]->supported_versions[j]); ++ if (version_pos < 0) { ++ break; ++ } ++ plugin_version_count[version_pos]++; ++ if (plugin_version_count[version_pos] == list->plugins_len) { ++ free(cni_version); ++ cni_version = util_strdup_s(get_support_version_by_pos(version_pos)); ++ goto free_out; ++ } ++ } ++ } ++ ++free_out: ++ free_cni_version_info_list(result_version_list); ++ return cni_version; ++} ++ + static int do_copy_plugin_args(const struct runtime_conf *rc, struct cni_args **cargs) + { + size_t i = 0; +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 878cb1bb..f94ab3f7 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/libcni_api.h ++++ b/src/daemon/modules/network/cni_operator/libcni/libcni_api.h +@@ -28,9 +28,6 @@ + extern "C" { + #endif + +-#define CURRENT_VERSION "1.0.0" +-#define SUPPORT_CACHE_AND_CHECK_VERSION "0.4.0" +- + #define SUPPORT_CAPABILITY_PORTMAPPINGS "portMappings" + #define SUPPORT_CAPABILITY_BANDWIDTH "bandwidth" + #define SUPPORT_CAPABILITY_IPRANGES "ipRanges" +@@ -87,6 +84,11 @@ int cni_del_network_list(const struct cni_network_list_conf *list, const struct + + int cni_check_network_list(const struct cni_network_list_conf *list, const struct runtime_conf *rc, + struct cni_opt_result **p_result); ++ ++int cni_version_network_list(const struct cni_network_list_conf *list, ++ struct cni_version_info_list **result_version_list); ++ ++char *cni_get_plugins_supported_version(cni_net_conf_list *list); + + void free_cni_port_mapping(struct cni_port_mapping *val); + +diff --git a/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c b/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c +index fd1091de..8a0ce1dd 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c ++++ b/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c +@@ -129,3 +129,21 @@ void free_cni_opt_result(struct cni_opt_result *val) + val->my_dns = NULL; + free(val); + } ++ ++void free_cni_version_info_list(struct cni_version_info_list *val) ++{ ++ size_t i = 0; ++ ++ if (val == NULL) { ++ return; ++ } ++ ++ for (i = 0; i < val->result_versions_len; i++) { ++ free_cni_version_info(val->result_versions[i]); ++ val->result_versions[i] = NULL; ++ } ++ free(val->result_versions); ++ val->result_versions = NULL; ++ ++ free(val); ++} +diff --git a/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.h b/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.h +index abbc22fe..36640e63 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.h ++++ b/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.h +@@ -19,10 +19,15 @@ + #include + #include + ++#include ++ + #ifdef __cplusplus + extern "C" { + #endif + ++#define CURRENT_VERSION "1.0.0" ++#define SUPPORT_CACHE_AND_CHECK_VERSION "0.4.0" ++ + /* define types for version */ + struct cni_opt_result_interface { + char *name; +@@ -73,6 +78,11 @@ struct cni_opt_result { + struct cni_opt_result_dns *my_dns; + }; + ++struct cni_version_info_list { ++ cni_version_info **result_versions; ++ size_t result_versions_len; ++}; ++ + void free_cni_opt_result_ipconfig(struct cni_opt_result_ipconfig *ipc); + + void free_cni_opt_result_route(struct cni_opt_result_route *val); +@@ -83,6 +93,8 @@ void free_cni_opt_result_dns(struct cni_opt_result_dns *val); + + void free_cni_opt_result(struct cni_opt_result *val); + ++void free_cni_version_info_list(struct cni_version_info_list *val); ++ + #ifdef __cplusplus + } + #endif +diff --git a/src/daemon/modules/network/native/adaptor_native.c b/src/daemon/modules/network/native/adaptor_native.c +index 4c63dec1..45288d7e 100644 +--- a/src/daemon/modules/network/native/adaptor_native.c ++++ b/src/daemon/modules/network/native/adaptor_native.c +@@ -26,6 +26,7 @@ + #include "linked_list.h" + #include "isulad_config.h" + #include ++#include + #include "utils_network.h" + #include "network_tools.h" + #include "cni_operate.h" +@@ -1301,7 +1302,7 @@ static cni_net_conf_list *conf_bridge(const network_create_request *request, str + list->plugins_len++; + } + +- list->cni_version = util_strdup_s(CURRENT_VERSION); ++ list->cni_version = cni_get_plugins_supported_version(list); + if (request->name != NULL) { + list->name = util_strdup_s(request->name); + } else { +-- +2.42.0 + diff --git a/0005-doc-support-version-opt.patch b/0005-doc-support-version-opt.patch new file mode 100644 index 0000000..39ebd5a --- /dev/null +++ b/0005-doc-support-version-opt.patch @@ -0,0 +1,87 @@ +From e314c2ba64b6f7a8b88566e6c01fac791c8e4186 Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Wed, 8 Nov 2023 16:03:50 +0800 +Subject: [PATCH 05/14] doc:support version opt + +--- + .../detailed/Network/cni_1.0.0_change.md | 24 ++++++++++++++++++- + .../detailed/Network/cni_operator_design.md | 8 +++++++ + .../Network/cni_operator_design_zh.md | 8 +++++++ + 3 files changed, 39 insertions(+), 1 deletion(-) + +diff --git a/docs/design/detailed/Network/cni_1.0.0_change.md b/docs/design/detailed/Network/cni_1.0.0_change.md +index 35dde2f7..a91225fb 100644 +--- a/docs/design/detailed/Network/cni_1.0.0_change.md ++++ b/docs/design/detailed/Network/cni_1.0.0_change.md +@@ -33,7 +33,29 @@ cni_net_conf_runtime_config; + ## 2. Execution Protocol + ### VERSION + +-VERSION操作用于检查插件支持的CNI规范的版本,在spec-v1.0.0中,它增加了输入参数cniVersion,iSulad未使用VERSION功能,因此不涉及。 ++VERSION操作用于检查插件支持的CNI规范的版本,在spec-v1.0.0中,它增加了输入参数cniVersion。 ++ ++整体时序: ++```mermaid ++sequenceDiagram ++ participant conf_bridge ++ participant cni_get_plugins_supported_version ++ participant cni_version_network_list ++ participant version_network ++ participant get_version_info ++ conf_bridge ->> cni_get_plugins_supported_version:post cni_net_conf_list ++ cni_get_plugins_supported_version ->> cni_version_network_list:post cni_net_conf_list ++ loop for each plugin ++ cni_version_network_list ->> version_network:post each cni_net_conf ++ version_network ->> get_version_info:post each cni_net_conf plugin path e.g. ++ get_version_info -->> version_network:get version_result ++ version_network -->> cni_version_network_list:get version_result ++ end ++ cni_version_network_list ->> cni_version_network_list:comb cni_version_info_list ++ cni_version_network_list -->> cni_get_plugins_supported_version:get cni_version_info_list ++ cni_get_plugins_supported_version ->> cni_get_plugins_supported_version:find the latest CNI version supported by all plugins ++ cni_get_plugins_supported_version -->> conf_bridge:get version ++``` + + ## 3. Execution of Network Configurations + +diff --git a/docs/design/detailed/Network/cni_operator_design.md b/docs/design/detailed/Network/cni_operator_design.md +index e77f4f94..64aaf2ed 100644 +--- a/docs/design/detailed/Network/cni_operator_design.md ++++ b/docs/design/detailed/Network/cni_operator_design.md +@@ -73,6 +73,14 @@ int detach_network_plane(const struct cni_manager *manager, const struct cni_net + * Return value: return 0 on success, non-zero on failure + */ + int check_network_plane(const struct cni_manager *manager, const struct cni_network_list_conf *list, struct cni_opt_result **result); ++ ++/* ++* Description: get the CNI version information supported by the plugins required for the single network plane of the container; ++* list: network configuration; ++* result_version_list: record the CNI version supported by the plugins; ++* Return value: return 0 on success, non-zero on failure ++*/ ++int version_network_plane(const struct cni_network_list_conf *list, struct cni_result_version_list **result_version_list); + ```` + + # 4. Detailed Design +diff --git a/docs/design/detailed/Network/cni_operator_design_zh.md b/docs/design/detailed/Network/cni_operator_design_zh.md +index ac88806e..6aa3c51a 100644 +--- a/docs/design/detailed/Network/cni_operator_design_zh.md ++++ b/docs/design/detailed/Network/cni_operator_design_zh.md +@@ -73,6 +73,14 @@ int detach_network_plane(const struct cni_manager *manager, const struct cni_net + * 返回值:成功返回0,失败返回非0 + */ + int check_network_plane(const struct cni_manager *manager, const struct cni_network_list_conf *list, struct cni_opt_result **result); ++ ++/* ++* 说明:获取容器单网络平面所需的插件支持的CNI版本信息; ++* list: 网络配置; ++* result_version_list:记录插件支持的CNI版本信息; ++* 返回值:成功返回0,失败返回非0 ++*/ ++int version_network_plane(const struct cni_network_list_conf *list, struct cni_result_version_list **result_version_list); + ``` + + # 4.详细设计 +-- +2.42.0 + diff --git a/0006-2242-disable-grpc-remote-connect-by-default.patch b/0006-2242-disable-grpc-remote-connect-by-default.patch new file mode 100644 index 0000000..8fa1bb0 --- /dev/null +++ b/0006-2242-disable-grpc-remote-connect-by-default.patch @@ -0,0 +1,26 @@ +From ee928d5af7ab7c42ee4597e1b6ae5871767c165d Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Mon, 13 Nov 2023 03:04:35 +0000 +Subject: [PATCH 06/14] !2242 disable grpc remote connect by default * disable + grpc remote connect by default + +--- + cmake/options.cmake | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/cmake/options.cmake b/cmake/options.cmake +index 8f1dfbbe..aeb24662 100644 +--- a/cmake/options.cmake ++++ b/cmake/options.cmake +@@ -106,7 +106,7 @@ if (ENABLE_SELINUX STREQUAL "ON") + message("${Green}-- Enable selinux${ColourReset}") + endif() + +-option(ENABLE_GRPC_REMOTE_CONNECT "enable gRPC remote connect" ON) ++option(ENABLE_GRPC_REMOTE_CONNECT "enable gRPC remote connect" OFF) + if (ENABLE_GRPC_REMOTE_CONNECT STREQUAL "ON") + add_definitions(-DENABLE_GRPC_REMOTE_CONNECT=1) + set(ENABLE_GRPC_REMOTE_CONNECT 1) +-- +2.42.0 + diff --git a/0007-2244-Save-task-address-of-shim-v2.patch b/0007-2244-Save-task-address-of-shim-v2.patch new file mode 100644 index 0000000..c7bf391 --- /dev/null +++ b/0007-2244-Save-task-address-of-shim-v2.patch @@ -0,0 +1,209 @@ +From 23945e20c418595a7a4037e9258f23aa7bed6b48 Mon Sep 17 00:00:00 2001 +From: jake +Date: Mon, 13 Nov 2023 08:15:12 +0000 +Subject: [PATCH 07/14] !2244 Save task address of shim v2 * Save task address + of shim v2 + +--- + .../v1/v1_cri_container_manager_service.cc | 6 ++ + .../v1alpha/cri_container_manager_service.cc | 5 ++ + src/daemon/modules/runtime/shim/shim_rt_ops.c | 86 ++++++++++++++----- + 3 files changed, 74 insertions(+), 23 deletions(-) + +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 1f20d2d2..f635df2b 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 +@@ -1013,6 +1013,12 @@ auto ContainerManagerService::ContainerStats(const std::string &containerID, Err + if (error.NotEmpty()) { + goto cleanup; + } ++ if (contStatsVec.size() == 0) { ++ ERROR("Failed to get container stats"); ++ error.SetError("Failed to get container stats"); ++ goto cleanup; ++ } ++ + contStats = std::move(contStatsVec[0]); + + cleanup: +diff --git a/src/daemon/entry/cri/v1alpha/cri_container_manager_service.cc b/src/daemon/entry/cri/v1alpha/cri_container_manager_service.cc +index 6f8ca114..9da25768 100644 +--- a/src/daemon/entry/cri/v1alpha/cri_container_manager_service.cc ++++ b/src/daemon/entry/cri/v1alpha/cri_container_manager_service.cc +@@ -1019,6 +1019,11 @@ auto ContainerManagerService::ContainerStats(const std::string &containerID, Err + if (error.NotEmpty()) { + goto cleanup; + } ++ if (contStatsVec.size() == 0) { ++ ERROR("Failed to get container stats"); ++ error.SetError("Failed to get container stats"); ++ goto cleanup; ++ } + contStats = std::move(contStatsVec[0]); + + cleanup: +diff --git a/src/daemon/modules/runtime/shim/shim_rt_ops.c b/src/daemon/modules/runtime/shim/shim_rt_ops.c +index d348dfe1..550b17f3 100644 +--- a/src/daemon/modules/runtime/shim/shim_rt_ops.c ++++ b/src/daemon/modules/runtime/shim/shim_rt_ops.c +@@ -16,13 +16,17 @@ + #define _GNU_SOURCE + + #include "shim_rt_ops.h" ++ + #include + #include + #include + #include + #include +-#include "isula_libutils/log.h" +-#include "isula_libutils/shim_client_process_state.h" ++ ++#include ++#include ++#include ++ + #include "utils.h" + #include "utils_string.h" + #include "constants.h" +@@ -318,16 +322,46 @@ bool rt_shim_detect(const char *runtime) + return false; + } + ++static int save_shim_v2_address(const char *bundle, const char *addr) ++{ ++ int nret; ++ char filename[PATH_MAX] = { 0 }; ++ ++ if (bundle == NULL) { ++ ERROR("Invalid input params"); ++ return -1; ++ } ++ ++ if (addr == NULL || strlen(addr) == 0) { ++ ERROR("Invalid shim v2 addr"); ++ return -1; ++ } ++ ++ nret = snprintf(filename, sizeof(filename), "%s/%s", bundle, "address"); ++ if (nret < 0 || (size_t)nret >= sizeof(filename)) { ++ ERROR("Failed to print string"); ++ return -1; ++ } ++ ++ nret = util_atomic_write_file(filename, addr, strlen(addr), CONFIG_FILE_MODE, false); ++ if (nret != 0) { ++ ERROR("Failed to write file %s", filename); ++ return -1; ++ } ++ ++ return 0; ++} ++ + int rt_shim_create(const char *id, const char *runtime, const rt_create_params_t *params) + { + int ret = 0; + int pid = 0; + int fd = -1; + const char *task_address = NULL; +- char addr[PATH_MAX] = {0}; +- char *exit_fifo_path = NULL; +- char *state_path = NULL; +- char *log_path = NULL; ++ char response[PATH_MAX] = {0}; ++ __isula_auto_free char *exit_fifo_path = NULL; ++ __isula_auto_free char *state_path = NULL; ++ __isula_auto_free char *log_path = NULL; + + if (id == NULL || runtime == NULL || params == NULL) { + ERROR("Invalid input params"); +@@ -337,29 +371,25 @@ int rt_shim_create(const char *id, const char *runtime, const rt_create_params_t + exit_fifo_path = util_path_dir(params->exit_fifo); + if (exit_fifo_path == NULL) { + ERROR("%s: failed to get exit fifo dir from %s", id, params->exit_fifo); +- ret = -1; +- goto out; ++ return -1; + } + + state_path = util_path_dir(exit_fifo_path); + if (state_path == NULL) { + ERROR("%s:failed to get state dir from %s", id, exit_fifo_path); +- ret = -1; +- goto out; ++ return -1; + } + + log_path = util_string_append(SHIM_V2_LOG, params->bundle); + if (log_path == NULL) { + ERROR("Fail to append log path"); +- ret = -1; +- goto out; ++ return -1; + } + + fd = util_open(log_path, O_RDWR | O_CREAT | O_TRUNC, DEFAULT_SECURE_FILE_MODE); + if (fd < 0) { + ERROR("Failed to create log file for shim v2: %s", log_path); +- ret = -1; +- goto out; ++ return -1; + } + close(fd); + +@@ -367,13 +397,13 @@ int rt_shim_create(const char *id, const char *runtime, const rt_create_params_t + * If task address is not set, create a new shim-v2 and get the address. + * If task address is set, use it directly. + */ +- if (params->task_addr == NULL) { +- if (shim_bin_v2_create(runtime, id, params->bundle, NULL, addr, state_path) != 0) { ++ if (params->task_addr == NULL || strlen(params->task_addr) == 0) { ++ if (shim_bin_v2_create(runtime, id, params->bundle, NULL, response, state_path) != 0) { + ERROR("%s: failed to create v2 shim", id); +- ret = -1; +- goto out; ++ return -1; + } +- task_address = addr; ++ ++ task_address = response; + } else { + task_address = params->task_addr; + } +@@ -392,10 +422,20 @@ int rt_shim_create(const char *id, const char *runtime, const rt_create_params_t + goto out; + } + ++ if (save_shim_v2_address(params->bundle, task_address) != 0) { ++ ERROR("%s: failed to save shim v2 address", id); ++ ret = -1; ++ goto out; ++ } ++ ++ return 0; ++ + out: +- free(log_path); +- free(exit_fifo_path); +- free(state_path); ++ if (ret != 0) { ++ if (shim_v2_kill(id, NULL, SIGKILL, false) != 0) { ++ ERROR("%s: kill shim v2 failed", id); ++ } ++ } + return ret; + } + +@@ -614,7 +654,7 @@ int rt_shim_status(const char *id, const char *runtime, const rt_status_params_t + return -1; + } + +- if (params->task_address != NULL) { ++ if (params->task_address != NULL && strlen(params->task_address) != 0) { + if (strlen(params->task_address) >= PATH_MAX) { + ERROR("Invalid task address"); + return -1; +-- +2.42.0 + diff --git a/0008-2233-add-runc-append-function-design-doc.patch b/0008-2233-add-runc-append-function-design-doc.patch new file mode 100644 index 0000000..c1fc023 --- /dev/null +++ b/0008-2233-add-runc-append-function-design-doc.patch @@ -0,0 +1,110 @@ +From 426b309efdee934f61a6fb27b278711aa5419dd5 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Mon, 13 Nov 2023 08:22:46 +0000 +Subject: [PATCH 08/14] !2233 add runc append function design doc * add runc + append function design doc + +--- + .../detailed/Runtime/runc_design_append.md | 75 +++++++++++++++++++ + docs/images/runc_isula_attach_flow_chart.svg | 5 ++ + 2 files changed, 80 insertions(+) + create mode 100644 docs/design/detailed/Runtime/runc_design_append.md + create mode 100644 docs/images/runc_isula_attach_flow_chart.svg + +diff --git a/docs/design/detailed/Runtime/runc_design_append.md b/docs/design/detailed/Runtime/runc_design_append.md +new file mode 100644 +index 00000000..aa17f558 +--- /dev/null ++++ b/docs/design/detailed/Runtime/runc_design_append.md +@@ -0,0 +1,75 @@ ++| Author | zhongtao | ++| ------ | --------------------- | ++| Date | 2023-10-19 | ++| Email | zhongtao17@huawei.com | ++ ++# 方案目标 ++ ++isulad当前默认的runtime为lcr + lxc,具有高性能的特点。但是该runtime是通过oci规范转换为lxc规范实现的,而且在lxc中进行了较多适配修改。 ++ ++随着oci 规范的日益成熟,oci规范实现的runtime能满足各种场景需求。因此iSulad实现基于oci 规范的runtime对接,具有底噪更低的优势。 ++ ++需求目标分为以下5点: ++ ++1. 对于isula 命令行支持 oci runtime 容器的功能进行全量排查,识别缺失功能。 ++2. 补齐缺失功能,保证切换默认runtime为runc之后功能的完整性,并针对新增功能补充对应的单元测试与门禁测试。 ++3. 梳理isulad-shim依赖情况,解耦isulad-shim依赖,减少runc容器底噪,并且提高稳定性(静态编译isulad-shim,从而使得isulad-shim不依赖isulad版本,支持isulad热升级) ++4. 重构社区门禁CI框架,支持多 runtime 测试。 ++ ++# 总体设计 ++ ++由于isulad与runc之间的交互存在gap,且将容器创建成功之后,容器进程的生命周期与isulad进程的生命周期没有必然联系,因此isulad设计了一个isulad-shim进程,用于isulad与runc的交互并将isulad与容器实例解耦。 ++ ++isulad 与 isulad-shim的关系以及整体结构请参照:[runc_design](./runc_design_zh.md) 。 ++ ++由于isula attach 涉及到attach中新建的fifo fd与容器首进程io进行数据交换,因此需要isulad与容器首进程对应的isulad-shim进行通信,完成建立io 连接并进行io copy操作。 ++ ++isula top 命令仅需要在isulad中直接调用runc二进制。 ++# 接口描述 ++ ++## isula_rt_ops模块 ++ ++```c ++ ++int rt_isula_attach(const char *id, const char *runtime, const rt_attach_params_t *params); ++ ++int rt_isula_listpids(const char *name, const char *runtime, const rt_listpids_params_t *params, ++ rt_listpids_out_t *out); ++``` ++# 详细设计 ++ ++## attach 实现流程 ++ ++### 流程图 ++ ++![runc_isula_attach_flow_chart](../../../images/runc_isula_attach_flow_chart.svg) ++ ++### 详细流程 ++ ++isulad端: ++ ++1. 创建容器时(rt_isula_create),传递给isulad-shim attach socket path; ++2. 进行attach操作时(rt_isula_attach),先根据 attach socket path与isulad-shim的socket server端建立连接,获得通信的socket fd。 ++3. 将attach 的stdin stdout与stderr fifo路径写入到socket fd中。 ++4. 从socket fd中读取isulad-shim是否成功将attach的fd加入到epoll中成功连接,若成功则直接成功返回,若失败则获取attach-log.json文件中的报错信息后报错返回。 ++ ++isulad-shim端: ++ ++1. create isulad-shim进程时,若传递的process 中包含 attach socket path, 则创建一个本地unix socket文件,用于isulad与isulad-shim之间通信。本地unix socket文件打开获得attach_isulad_fd,将attach_isulad_fd加入到epoll需要监听的fd中。 ++2. 收到attach_isulad_fd的事件后,调用do_attach_socket_accept函数,accept到通信的conn_fd后,将conn_fd加入到epoll需要监听的fd中。 ++3. 在收到conn_fd事件后,调用attach_fd函数。attach_fd函数中从attach_isulad_fd中读出stdin stdout与stderr路径,之后在shim中打开fd。将stdin对应的fd加入epoll监听列表中,有事件时调用stdin_cb。若容器有输入与输出,则除了写入到初始isulad fd中之外,还需要写入到attach的fd list中。 ++ ++### 新增文件 ++1. /run/isulad/runc/{container_id}/attach_socket.sock 用于isulad与isulad-shim attach通信 ++2. /run/isulad/runc/{container_id}/attach-log.json 用于记录isulad-shim中attach的报错信息。目前所有的attach操作共用一个attach文件 ++ ++### 未来规划 ++1. runc容器的attach支持魔术符退出(CTRL + Q),退出后不影响容器首进程的运行,也不影响其他并发的attach操作。 ++2. 由于支持魔术符退出,在GRPC版本中,可设置了ISULAD_INFO_DETACH错误码,用于标识用户输入魔术符退出,而rest版本中由于实现差异,无法识别exit退出与魔术符退出的差异,因此在魔术符退出时,会存在一条INFO级别的报错信息:`INFO("Wait container stopped status timeout.");` ++ ++## top 实现流程 ++ ++isulad端: ++ ++1. 直接调用runc二进制ps容器:runtime_call_simple(), 设置选项" --format json"; ++2. 直接解析调用返回的stdout中的容器进程pid,将其写入到rt_listpids_out_t结构体中; +\ No newline at end of file +diff --git a/docs/images/runc_isula_attach_flow_chart.svg b/docs/images/runc_isula_attach_flow_chart.svg +new file mode 100644 +index 00000000..e57a4ec0 +--- /dev/null ++++ b/docs/images/runc_isula_attach_flow_chart.svg +@@ -0,0 +1,5 @@ ++ ++ ++ ++ ++ rt_isula_createattach socket pathcreate local unix socket forattach: attach_socket_fdruntime_createisuladisulad-shimmanagecontainerfirst processadd attach_socket_fd to epoll looprt_isula_attachconnectget_attach_socketfddo_attach_socket_acceptadd conn_fd to epoll loopwrite attach isulad fdto socket fdget_container_attach_exitcodeattach_cbread isulad fd from attach conn fdeventattach connections nums exceeds the limit?yeserror exitwrite -1 to conn fdnoadd_attach_terminal_fifosadd fifofd_in fd to epoll loopsuccess exitwrite 0 to conn fdIoCopy threadisula_epoll_loop threadsio stream +\ No newline at end of file +-- +2.42.0 + diff --git a/0009-2243-Refactor-capbilities-specs.patch b/0009-2243-Refactor-capbilities-specs.patch new file mode 100644 index 0000000..116a30f --- /dev/null +++ b/0009-2243-Refactor-capbilities-specs.patch @@ -0,0 +1,1056 @@ +From e84112fd7128e05a1a4a380d8242c672d1f539f9 Mon Sep 17 00:00:00 2001 +From: xuxuepeng +Date: Mon, 13 Nov 2023 08:44:15 +0000 +Subject: [PATCH 09/14] !2243 Refactor capbilities specs * Refactor capbilities + specs + +--- + src/cmd/isula/isula_host_spec.c | 1 + + src/daemon/modules/spec/specs.c | 12 +- + src/daemon/modules/spec/specs_security.c | 140 ++++---- + src/utils/cutils/utils_cap.c | 119 +++++++ + src/utils/cutils/utils_cap.h | 39 +++ + src/utils/cutils/utils_verify.c | 81 ----- + src/utils/cutils/utils_verify.h | 6 - + test/cutils/utils_verify/utils_verify_ut.cc | 14 - + .../image/oci/oci_config_merge/CMakeLists.txt | 1 + + test/image/oci/storage/images/CMakeLists.txt | 1 + + test/specs/specs/CMakeLists.txt | 1 + + test/specs/specs/oci_runtime_spec.json | 32 ++ + test/specs/specs/specs_ut.cc | 315 ++++++++++++++++++ + test/specs/specs_extend/CMakeLists.txt | 1 + + 14 files changed, 573 insertions(+), 190 deletions(-) + create mode 100644 src/utils/cutils/utils_cap.c + create mode 100644 src/utils/cutils/utils_cap.h + +diff --git a/src/cmd/isula/isula_host_spec.c b/src/cmd/isula/isula_host_spec.c +index 6f39588d..09dea271 100644 +--- a/src/cmd/isula/isula_host_spec.c ++++ b/src/cmd/isula/isula_host_spec.c +@@ -36,6 +36,7 @@ + #include "utils_file.h" + #include "utils_string.h" + #include "utils_verify.h" ++#include "utils_cap.h" + #include "opt_ulimit.h" + + static bool parse_restart_policy(const char *policy, host_config_restart_policy **rp) +diff --git a/src/daemon/modules/spec/specs.c b/src/daemon/modules/spec/specs.c +index 95346603..cc49d85f 100644 +--- a/src/daemon/modules/spec/specs.c ++++ b/src/daemon/modules/spec/specs.c +@@ -49,6 +49,7 @@ + #include "utils_file.h" + #include "utils_string.h" + #include "utils_verify.h" ++#include "utils_cap.h" + + #ifndef CLONE_NEWUTS + #define CLONE_NEWUTS 0x04000000 +@@ -814,15 +815,16 @@ static int adapt_settings_for_privileged(oci_runtime_spec *oci_spec, bool privil + { + int ret = 0; + size_t all_caps_len = 0; ++ const char **all_caps = NULL; + + if (!privileged) { + return 0; + } + +- all_caps_len = util_get_all_caps_len(); +- if (oci_spec == NULL) { +- ret = -1; +- goto out; ++ all_caps = util_get_all_caps(&all_caps_len); ++ if (all_caps == NULL) { ++ ERROR("Failed to get all capabilities"); ++ return -1; + } + + clean_correlated_items(oci_spec); +@@ -838,7 +840,7 @@ static int adapt_settings_for_privileged(oci_runtime_spec *oci_spec, bool privil + goto out; + } + +- ret = refill_oci_process_capabilities(&oci_spec->process->capabilities, g_all_caps, all_caps_len); ++ ret = refill_oci_process_capabilities(&oci_spec->process->capabilities, all_caps, all_caps_len); + if (ret != 0) { + ERROR("Failed to copy all capabilities"); + ret = -1; +diff --git a/src/daemon/modules/spec/specs_security.c b/src/daemon/modules/spec/specs_security.c +index e78cc744..b34aec7c 100644 +--- a/src/daemon/modules/spec/specs_security.c ++++ b/src/daemon/modules/spec/specs_security.c +@@ -37,6 +37,7 @@ + #include "utils_array.h" + #include "utils_string.h" + #include "utils_verify.h" ++#include "utils_cap.h" + + #define MAX_CAP_LEN 32 + +@@ -104,41 +105,31 @@ static int tweak_drops_capabilities(char ***new_caps, size_t *new_caps_len, char + size_t i = 0; + int ret = 0; + +- if (util_strings_in_slice((const char **)drops, drops_len, "all")) { +- goto out; ++ if (basic_caps == NULL || basic_caps_len == 0) { ++ *new_caps = NULL; ++ *new_caps_len = 0; ++ return 0; + } + +- for (i = 0; (basic_caps != NULL && i < basic_caps_len); i++) { +- // skip `all` already handled above +- if (!basic_caps[i] || !strcasecmp(basic_caps[i], "all")) { +- continue; +- } +- +- // if we don't drop `all`, add back all the non-dropped caps ++ for (i = 0; i < basic_caps_len; i++) { + if (!util_strings_in_slice((const char **)drops, drops_len, basic_caps[i] + strlen("CAP_"))) { + ret = append_capability(new_caps, new_caps_len, basic_caps[i]); + if (ret != 0) { + ERROR("Failed to append capabilities"); +- ret = -1; +- goto out; ++ return -1; + } + } + } + +-out: +- return ret; ++ return 0; + } + + static int tweak_adds_capabilities(char ***new_caps, size_t *new_caps_len, const char **adds, size_t adds_len) + { + size_t i = 0; +- int ret = 0; + int nret = 0; +- size_t all_caps_len = 0; + char tmpcap[MAX_CAP_LEN] = { 0 }; + +- all_caps_len = util_get_all_caps_len(); +- + for (i = 0; i < adds_len; i++) { + // skip `all` already handled above + if (strcasecmp(adds[i], "all") == 0) { +@@ -148,111 +139,92 @@ static int tweak_adds_capabilities(char ***new_caps, size_t *new_caps_len, const + nret = snprintf(tmpcap, sizeof(tmpcap), "CAP_%s", adds[i]); + if (nret < 0 || (size_t)nret >= sizeof(tmpcap)) { + ERROR("Failed to print string"); +- ret = -1; +- goto out; +- } +- if (!util_strings_in_slice(g_all_caps, all_caps_len, tmpcap)) { +- ERROR("Unknown capability to add: '%s'", tmpcap); +- ret = -1; +- goto out; ++ return -1; + } + + // add cap if not already in the list + if (!util_strings_in_slice((const char **)*new_caps, *new_caps_len, tmpcap)) { +- ret = append_capability(new_caps, new_caps_len, tmpcap); +- if (ret != 0) { ++ nret = append_capability(new_caps, new_caps_len, tmpcap); ++ if (nret != 0) { + ERROR("Failed to append capabilities"); +- ret = -1; +- goto out; ++ return -1; + } + } + } + +-out: +- return ret; +-} +- +-static bool valid_drops_cap(const char **drops, size_t drops_len) +-{ +- int nret = 0; +- size_t i; +- size_t all_caps_len = 0; +- char tmpcap[MAX_CAP_LEN] = { 0 }; +- +- all_caps_len = util_get_all_caps_len(); +- // look for invalid cap in the drop list +- for (i = 0; i < drops_len; i++) { +- if (strcasecmp(drops[i], "all") == 0) { +- continue; +- } +- +- nret = snprintf(tmpcap, sizeof(tmpcap), "CAP_%s", drops[i]); +- if (nret < 0 || (size_t)nret >= sizeof(tmpcap)) { +- ERROR("Failed to print string"); +- return false; +- } +- if (!util_strings_in_slice(g_all_caps, all_caps_len, tmpcap)) { +- ERROR("Unknown capability to drop: '%s'", drops[i]); +- return false; +- } +- } +- +- return true; ++ return 0; + } + + // tweak_capabilities can tweak capabilities by adding or dropping capabilities +-// based on the basic capabilities. ++// based on the basic capabilities. The following are the priorities of the tweaks: ++// 1. if adds contains "all", then the basic capabilities will be ignored, and all capabilities will be added. ++// 2. if drops contains "all", all capabilities will be dropped. ++// 3. add individual capabilities in adds ++// 4. drop individual capabilities in drops. ++// The reason why we handle "all" first is that we can avoid the case that the individual capabilities are ++// not included by "all". + static int tweak_capabilities(char ***caps, size_t *caps_len, const char **adds, size_t adds_len, const char **drops, + size_t drops_len) + { +- size_t i; +- size_t all_caps_len = 0; + int ret = 0; + char **new_caps = NULL; + char **basic_caps = NULL; ++ const char **all_caps = NULL; + size_t new_caps_len = 0; + size_t basic_caps_len = 0; ++ size_t all_caps_len = 0; ++ bool add_all = false; ++ bool drop_all = false; + +- all_caps_len = util_get_all_caps_len(); +- if (!valid_drops_cap(drops, drops_len)) { ++ all_caps = util_get_all_caps(&all_caps_len); ++ if (all_caps == NULL) { ++ ERROR("Failed to get all capabilities"); + return -1; + } + +- if (util_strings_in_slice((const char **)adds, adds_len, "all")) { +- ret = copy_capabilities(&basic_caps, &basic_caps_len, g_all_caps, all_caps_len); +- } else { ++ add_all = util_strings_in_slice((const char **)adds, adds_len, "all"); ++ drop_all = util_strings_in_slice((const char **)drops, drops_len, "all"); ++ ++ ++ if (!add_all && !drop_all) { ++ // if neither add_all nor drop_all, we start with the default capabilities + ret = copy_capabilities(&basic_caps, &basic_caps_len, (const char **)*caps, *caps_len); +- } +- if (ret != 0) { +- ERROR("Failed to copy capabilities"); +- ret = -1; +- goto free_out; ++ if (ret != 0) { ++ ERROR("Failed to copy capabilities"); ++ ret = -1; ++ goto free_out; ++ } ++ } else if (drop_all) { ++ // if drop_all, we start with an empty set ++ basic_caps = NULL; ++ basic_caps_len = 0; ++ } else { ++ // if not drop_all but add_all, we start with all capabilities ++ ret = copy_capabilities(&basic_caps, &basic_caps_len, all_caps, all_caps_len); ++ if (ret != 0) { ++ ERROR("Failed to copy all capabilities"); ++ ret = -1; ++ goto free_out; ++ } + } + +- ret = tweak_drops_capabilities(&new_caps, &new_caps_len, basic_caps, basic_caps_len, drops, drops_len); ++ // Add capabilities to the basic capabilities ++ ret = tweak_adds_capabilities(&basic_caps, &basic_caps_len, adds, adds_len); + if (ret != 0) { + ret = -1; + goto free_out; + } + +- ret = tweak_adds_capabilities(&new_caps, &new_caps_len, adds, adds_len); ++ // Drop capabilities from the basic capabilities ++ ret = tweak_drops_capabilities(&new_caps, &new_caps_len, basic_caps, basic_caps_len, drops, drops_len); + if (ret != 0) { + ret = -1; + goto free_out; + } + + free_out: +- for (i = 0; i < basic_caps_len; i++) { +- free(basic_caps[i]); +- } +- free(basic_caps); +- +- // free old caps +- for (i = 0; i < *caps_len; i++) { +- free((*caps)[i]); +- (*caps)[i] = NULL; +- } +- free(*caps); ++ util_free_array_by_len(basic_caps, basic_caps_len); ++ util_free_array_by_len(*caps, *caps_len); + + // set new caps + *caps = new_caps; +diff --git a/src/utils/cutils/utils_cap.c b/src/utils/cutils/utils_cap.c +new file mode 100644 +index 00000000..6473df45 +--- /dev/null ++++ b/src/utils/cutils/utils_cap.c +@@ -0,0 +1,119 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2018-2022. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: xuxuepeng ++ * Create: 2023-11-08 ++ * Description: provide capbilities utils functions ++ *******************************************************************************/ ++ ++#define _GNU_SOURCE ++ ++#include "utils_cap.h" ++ ++#include ++#include ++#include ++ ++#include "utils_string.h" ++ ++const char *g_all_caps[] = { ++ "CAP_CHOWN", ++ "CAP_DAC_OVERRIDE", ++ "CAP_DAC_READ_SEARCH", ++ "CAP_FOWNER", ++ "CAP_FSETID", ++ "CAP_KILL", ++ "CAP_SETGID", ++ "CAP_SETUID", ++ "CAP_SETPCAP", ++ "CAP_LINUX_IMMUTABLE", ++ "CAP_NET_BIND_SERVICE", ++ "CAP_NET_BROADCAST", ++ "CAP_NET_ADMIN", ++ "CAP_NET_RAW", ++ "CAP_IPC_LOCK", ++ "CAP_IPC_OWNER", ++ "CAP_SYS_MODULE", ++ "CAP_SYS_RAWIO", ++ "CAP_SYS_CHROOT", ++ "CAP_SYS_PTRACE", ++ "CAP_SYS_PACCT", ++ "CAP_SYS_ADMIN", ++ "CAP_SYS_BOOT", ++ "CAP_SYS_NICE", ++ "CAP_SYS_RESOURCE", ++ "CAP_SYS_TIME", ++ "CAP_SYS_TTY_CONFIG", ++ "CAP_MKNOD", ++ "CAP_LEASE", ++#ifdef CAP_AUDIT_WRITE ++ "CAP_AUDIT_WRITE", ++#endif ++#ifdef CAP_AUDIT_CONTROL ++ "CAP_AUDIT_CONTROL", ++#endif ++ "CAP_SETFCAP", ++ "CAP_MAC_OVERRIDE", ++ "CAP_MAC_ADMIN", ++#ifdef CAP_SYSLOG ++ "CAP_SYSLOG", ++#endif ++#ifdef CAP_WAKE_ALARM ++ "CAP_WAKE_ALARM", ++#endif ++#ifdef CAP_BLOCK_SUSPEND ++ "CAP_BLOCK_SUSPEND", ++#endif ++#ifdef CAP_AUDIT_READ ++ "CAP_AUDIT_READ", ++#endif ++#ifdef CAP_PERFMON ++ "CAP_PERFMON", ++#endif ++#ifdef CAP_BPF ++ "CAP_BPF", ++#endif ++#ifdef CAP_CHECKPOINT_RESTORE ++ "CAP_CHECKPOINT_RESTORE", ++#endif ++}; ++ ++static inline size_t util_get_all_caps_len() ++{ ++ return sizeof(g_all_caps) / sizeof(char *); ++} ++ ++bool util_valid_cap(const char *cap) ++{ ++ int nret = 0; ++ char tmpcap[32] = { 0 }; ++ size_t all_caps_len = util_get_all_caps_len(); ++ ++ if (cap == NULL) { ++ return false; ++ } ++ ++ nret = snprintf(tmpcap, sizeof(tmpcap), "CAP_%s", cap); ++ if (nret < 0 || (size_t)nret >= sizeof(tmpcap)) { ++ ERROR("Failed to print string"); ++ return false; ++ } ++ if (!util_strings_in_slice(g_all_caps, all_caps_len, tmpcap)) { ++ return false; ++ } ++ ++ return true; ++} ++ ++const char **util_get_all_caps(size_t *cap_len) ++{ ++ *cap_len = util_get_all_caps_len(); ++ return g_all_caps; ++} +diff --git a/src/utils/cutils/utils_cap.h b/src/utils/cutils/utils_cap.h +new file mode 100644 +index 00000000..de63d070 +--- /dev/null ++++ b/src/utils/cutils/utils_cap.h +@@ -0,0 +1,39 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2018-2022. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: xuxuepeng ++ * Create: 2023-11-08 ++ * Description: provide capbilities utils functions ++ *******************************************************************************/ ++ ++#ifndef UTILS_CUTILS_UTILS_CAP_H ++#define UTILS_CUTILS_UTILS_CAP_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include ++#include ++#include ++ ++bool util_valid_cap(const char *cap); ++ ++/** ++ * Get all supported capabilities for linux, ++ * note that the returned strings are unmutable ++ */ ++const char **util_get_all_caps(size_t *cap_len); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // UTILS_CUTILS_UTILS_CAP_H +diff --git a/src/utils/cutils/utils_verify.c b/src/utils/cutils/utils_verify.c +index 2f10f278..f4ce3199 100644 +--- a/src/utils/cutils/utils_verify.c ++++ b/src/utils/cutils/utils_verify.c +@@ -22,7 +22,6 @@ + #include + #include + #include +-#include + #include + #include + +@@ -32,59 +31,6 @@ + #include "utils_array.h" + #include "utils_string.h" + +-const char *g_all_caps[] = { +- "CAP_CHOWN", +- "CAP_DAC_OVERRIDE", +- "CAP_DAC_READ_SEARCH", +- "CAP_FOWNER", +- "CAP_FSETID", +- "CAP_KILL", +- "CAP_SETGID", +- "CAP_SETUID", +- "CAP_SETPCAP", +- "CAP_LINUX_IMMUTABLE", +- "CAP_NET_BIND_SERVICE", +- "CAP_NET_BROADCAST", +- "CAP_NET_ADMIN", +- "CAP_NET_RAW", +- "CAP_IPC_LOCK", +- "CAP_IPC_OWNER", +- "CAP_SYS_MODULE", +- "CAP_SYS_RAWIO", +- "CAP_SYS_CHROOT", +- "CAP_SYS_PTRACE", +- "CAP_SYS_PACCT", +- "CAP_SYS_ADMIN", +- "CAP_SYS_BOOT", +- "CAP_SYS_NICE", +- "CAP_SYS_RESOURCE", +- "CAP_SYS_TIME", +- "CAP_SYS_TTY_CONFIG", +- "CAP_MKNOD", +- "CAP_LEASE", +-#ifdef CAP_AUDIT_WRITE +- "CAP_AUDIT_WRITE", +-#endif +-#ifdef CAP_AUDIT_CONTROL +- "CAP_AUDIT_CONTROL", +-#endif +- "CAP_SETFCAP", +- "CAP_MAC_OVERRIDE", +- "CAP_MAC_ADMIN", +-#ifdef CAP_SYSLOG +- "CAP_SYSLOG", +-#endif +-#ifdef CAP_WAKE_ALARM +- "CAP_WAKE_ALARM", +-#endif +-#ifdef CAP_BLOCK_SUSPEND +- "CAP_BLOCK_SUSPEND", +-#endif +-#ifdef CAP_AUDIT_READ +- "CAP_AUDIT_READ", +-#endif +-}; +- + bool util_valid_cmd_arg(const char *arg) + { + return (arg != NULL) && (strchr(arg, '|') == NULL) && (strchr(arg, '`') == NULL) && (strchr(arg, '&')) == NULL && +@@ -215,33 +161,6 @@ bool util_valid_str(const char *str) + return (str != NULL && str[0] != '\0') ? true : false; + } + +-size_t util_get_all_caps_len() +-{ +- return sizeof(g_all_caps) / sizeof(char *); +-} +- +-bool util_valid_cap(const char *cap) +-{ +- int nret = 0; +- char tmpcap[32] = { 0 }; +- size_t all_caps_len = util_get_all_caps_len(); +- +- if (cap == NULL) { +- return false; +- } +- +- nret = snprintf(tmpcap, sizeof(tmpcap), "CAP_%s", cap); +- if (nret < 0 || (size_t)nret >= sizeof(tmpcap)) { +- ERROR("Failed to print string"); +- return false; +- } +- if (!util_strings_in_slice(g_all_caps, all_caps_len, tmpcap)) { +- return false; +- } +- +- return true; +-} +- + bool util_valid_container_id(const char *id) + { + char *patten = "^[a-f0-9]{1,64}$"; +diff --git a/src/utils/cutils/utils_verify.h b/src/utils/cutils/utils_verify.h +index ad4466ef..54d1ce71 100644 +--- a/src/utils/cutils/utils_verify.h ++++ b/src/utils/cutils/utils_verify.h +@@ -38,8 +38,6 @@ extern "C" { + + #define VALID_VOLUME_NAME "[a-zA-Z0-9][a-zA-Z0-9_.-]{1,63}" + +-extern const char *g_all_caps[]; +- + bool util_valid_cmd_arg(const char *arg); + + bool util_valid_signal(int sig); +@@ -54,10 +52,6 @@ bool util_valid_device_mode(const char *mode); + + bool util_valid_str(const char *str); + +-size_t util_get_all_caps_len(); +- +-bool util_valid_cap(const char *cap); +- + bool util_valid_time_tz(const char *time); + + bool util_valid_embedded_image_name(const char *name); +diff --git a/test/cutils/utils_verify/utils_verify_ut.cc b/test/cutils/utils_verify/utils_verify_ut.cc +index 99775d09..79670ec1 100644 +--- a/test/cutils/utils_verify/utils_verify_ut.cc ++++ b/test/cutils/utils_verify/utils_verify_ut.cc +@@ -98,20 +98,6 @@ TEST(utils_verify, test_util_valid_str) + ASSERT_EQ(util_valid_str(nullptr), false); + } + +-TEST(utils_verify, test_util_get_all_caps_len) +-{ +- ASSERT_NE(util_get_all_caps_len(), 0); +-} +- +-TEST(utils_verify, test_util_valid_cap) +-{ +- ASSERT_EQ(util_valid_cap("DAC_READ_SEARCH"), true); +- +- ASSERT_EQ(util_valid_cap(nullptr), false); +- ASSERT_EQ(util_valid_cap(""), false); +- ASSERT_EQ(util_valid_cap("DA_READ_SEARCH"), false); +-} +- + TEST(utils_verify, test_util_valid_time_tz) + { + ASSERT_EQ(util_valid_time_tz("2022-10-04T18:22:45.289257759Z"), true); +diff --git a/test/image/oci/oci_config_merge/CMakeLists.txt b/test/image/oci/oci_config_merge/CMakeLists.txt +index ce4df5ba..90809080 100644 +--- a/test/image/oci/oci_config_merge/CMakeLists.txt ++++ b/test/image/oci/oci_config_merge/CMakeLists.txt +@@ -14,6 +14,7 @@ add_executable(${EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/cutils/utils_file.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/cutils/utils_timestamp.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/cutils/utils_fs.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/cutils/utils_cap.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/cutils/map/map.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/cutils/map/rb_tree.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/cutils/util_atomic.c +diff --git a/test/image/oci/storage/images/CMakeLists.txt b/test/image/oci/storage/images/CMakeLists.txt +index 8446ebba..28e0b505 100644 +--- a/test/image/oci/storage/images/CMakeLists.txt ++++ b/test/image/oci/storage/images/CMakeLists.txt +@@ -11,6 +11,7 @@ add_executable(${EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cutils/utils_convert.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cutils/utils_file.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cutils/utils_base64.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cutils/utils_cap.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cutils/util_atomic.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/sha256/sha256.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../src/utils/cutils/path.c +diff --git a/test/specs/specs/CMakeLists.txt b/test/specs/specs/CMakeLists.txt +index 1d627e37..a9dbc52c 100644 +--- a/test/specs/specs/CMakeLists.txt ++++ b/test/specs/specs/CMakeLists.txt +@@ -14,6 +14,7 @@ add_executable(${EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/util_atomic.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_mount_spec.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_fs.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_cap.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/sha256/sha256.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/path.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/map/map.c +diff --git a/test/specs/specs/oci_runtime_spec.json b/test/specs/specs/oci_runtime_spec.json +index 0223fd6f..efd5da35 100644 +--- a/test/specs/specs/oci_runtime_spec.json ++++ b/test/specs/specs/oci_runtime_spec.json +@@ -154,6 +154,38 @@ + "CAP_SYS_CHROOT", + "CAP_KILL", + "CAP_AUDIT_WRITE" ++ ], ++ "effective": [ ++ "CAP_CHOWN", ++ "CAP_DAC_OVERRIDE", ++ "CAP_FSETID", ++ "CAP_FOWNER", ++ "CAP_MKNOD", ++ "CAP_NET_RAW", ++ "CAP_SETGID", ++ "CAP_SETUID", ++ "CAP_SETFCAP", ++ "CAP_SETPCAP", ++ "CAP_NET_BIND_SERVICE", ++ "CAP_SYS_CHROOT", ++ "CAP_KILL", ++ "CAP_AUDIT_WRITE" ++ ], ++ "permitted": [ ++ "CAP_CHOWN", ++ "CAP_DAC_OVERRIDE", ++ "CAP_FSETID", ++ "CAP_FOWNER", ++ "CAP_MKNOD", ++ "CAP_NET_RAW", ++ "CAP_SETGID", ++ "CAP_SETUID", ++ "CAP_SETFCAP", ++ "CAP_SETPCAP", ++ "CAP_NET_BIND_SERVICE", ++ "CAP_SYS_CHROOT", ++ "CAP_KILL", ++ "CAP_AUDIT_WRITE" + ] + } + }, +diff --git a/test/specs/specs/specs_ut.cc b/test/specs/specs/specs_ut.cc +index 96aa1c63..ad903a3f 100644 +--- a/test/specs/specs/specs_ut.cc ++++ b/test/specs/specs/specs_ut.cc +@@ -20,6 +20,7 @@ + #include "isula_libutils/oci_runtime_spec.h" + #include "specs_api.h" + #include "specs_namespace.h" ++#include "specs_security.h" + #include "isula_libutils/host_config.h" + #include "isula_libutils/container_config.h" + #include "oci_ut_common.h" +@@ -27,6 +28,7 @@ + #include + #include "isulad_config_mock.h" + #include "utils.h" ++#include "utils_cap.h" + + using ::testing::Args; + using ::testing::ByRef; +@@ -344,3 +346,316 @@ TEST_F(SpecsUnitTest, test_merge_container_cgroups_path_5) + + testing::Mock::VerifyAndClearExpectations(&m_isulad_conf); + } ++ ++/********************************* UT for merge caps *******************************************/ ++struct capabilities_lens { ++ size_t bounding_len; ++ size_t effective_len; ++ size_t inheritable_len; ++ size_t permitted_len; ++ size_t ambient_len; ++}; ++ ++void check_capabilities_len(defs_process_capabilities *cap, struct capabilities_lens *lens) ++{ ++ lens->bounding_len = cap->bounding_len; ++ lens->effective_len = cap->effective_len; ++ lens->inheritable_len = cap->inheritable_len; ++ lens->permitted_len = cap->permitted_len; ++ lens->ambient_len = cap->ambient_len; ++} ++ ++void validate_capabilities_len(defs_process_capabilities *cap, struct capabilities_lens *lens, ssize_t len_diff) ++{ ++ ASSERT_EQ((ssize_t)cap->bounding_len, (ssize_t)lens->bounding_len + len_diff); ++ ASSERT_EQ((ssize_t)cap->effective_len, (ssize_t)lens->effective_len + len_diff); ++ ASSERT_EQ((ssize_t)cap->permitted_len, (ssize_t)lens->permitted_len + len_diff); ++ // Currently we don't support inheritable and ambient capabilities ++} ++ ++TEST(merge_capability_ut, test_merge_caps_without_adds_drops) ++{ ++ oci_runtime_spec *oci_spec = nullptr; ++ int ret = 0; ++ char *err = nullptr; ++ struct capabilities_lens old_lens = { 0 }; ++ char *oci_config_file = nullptr; ++ ++ oci_config_file = json_path(OCI_RUNTIME_SPEC_FILE); ++ ASSERT_TRUE(oci_config_file != nullptr); ++ ++ ++ oci_spec = oci_runtime_spec_parse_file(oci_config_file, nullptr, &err); ++ ASSERT_TRUE(oci_spec != nullptr); ++ free(err); ++ ++ check_capabilities_len(oci_spec->process->capabilities, &old_lens); ++ ++ ret = merge_caps(oci_spec, nullptr, 0, nullptr, 0); ++ ASSERT_EQ(ret, 0); ++ ++ validate_capabilities_len(oci_spec->process->capabilities, &old_lens, 0); ++ ++ free_oci_runtime_spec(oci_spec); ++} ++ ++TEST(merge_capability_ut, test_merge_caps_adds_without_drops) ++{ ++ oci_runtime_spec *oci_spec = nullptr; ++ int ret = 0; ++ char *err = nullptr; ++ struct capabilities_lens old_lens = { 0 }; ++ char *oci_config_file = nullptr; ++ /* All of below capabilities are not in oci_config_file */ ++ const char *adds[] = { "NET_ADMIN", "SYS_ADMIN", "SYS_TTY_CONFIG", "SYS_PTRACE" }; ++ const char *drops[] = {}; ++ size_t adds_len = sizeof(adds) / sizeof(adds[0]); ++ size_t drops_len = sizeof(drops) / sizeof(drops[0]); ++ ++ oci_config_file = json_path(OCI_RUNTIME_SPEC_FILE); ++ ASSERT_TRUE(oci_config_file != nullptr); ++ ++ ++ oci_spec = oci_runtime_spec_parse_file(oci_config_file, nullptr, &err); ++ ASSERT_TRUE(oci_spec != nullptr); ++ free(err); ++ ++ check_capabilities_len(oci_spec->process->capabilities, &old_lens); ++ ++ ret = merge_caps(oci_spec, adds, adds_len, drops, drops_len); ++ ASSERT_EQ(ret, 0); ++ ++ /* All of capabilities in adds are added */ ++ validate_capabilities_len(oci_spec->process->capabilities, &old_lens, adds_len); ++ ++ free_oci_runtime_spec(oci_spec); ++} ++ ++TEST(merge_capability_ut, test_merge_caps_adds_existing_without_drops) ++{ ++ oci_runtime_spec *oci_spec = nullptr; ++ int ret = 0; ++ char *err = nullptr; ++ struct capabilities_lens old_lens = { 0 }; ++ char *oci_config_file = nullptr; ++ /* CHOWN already exits in oci_config_file */ ++ const char *adds[] = { "CHOWN", "SYS_ADMIN", "SYS_TTY_CONFIG", "SYS_PTRACE" }; ++ const char *drops[] = {}; ++ size_t adds_len = sizeof(adds) / sizeof(adds[0]); ++ size_t drops_len = sizeof(drops) / sizeof(drops[0]); ++ ++ oci_config_file = json_path(OCI_RUNTIME_SPEC_FILE); ++ ASSERT_TRUE(oci_config_file != nullptr); ++ ++ ++ oci_spec = oci_runtime_spec_parse_file(oci_config_file, nullptr, &err); ++ ASSERT_TRUE(oci_spec != nullptr); ++ free(err); ++ ++ check_capabilities_len(oci_spec->process->capabilities, &old_lens); ++ ++ ret = merge_caps(oci_spec, adds, adds_len, drops, drops_len); ++ ASSERT_EQ(ret, 0); ++ ++ /* CHOWN is not added, since it already exits in the default list */ ++ validate_capabilities_len(oci_spec->process->capabilities, &old_lens, adds_len - 1); ++ ++ free_oci_runtime_spec(oci_spec); ++} ++ ++TEST(merge_capability_ut, test_merge_caps_drops_without_adds) ++{ ++ oci_runtime_spec *oci_spec = nullptr; ++ int ret = 0; ++ char *err = nullptr; ++ struct capabilities_lens old_lens = { 0 }; ++ char *oci_config_file = nullptr; ++ const char *adds[] = {}; ++ /* Below capabilities are not in the oci_config_file */ ++ const char *drops[] = { "SYS_TTY_CONFIG", "SYS_PTRACE" }; ++ size_t adds_len = sizeof(adds) / sizeof(adds[0]); ++ size_t drops_len = sizeof(drops) / sizeof(drops[0]); ++ ++ oci_config_file = json_path(OCI_RUNTIME_SPEC_FILE); ++ ASSERT_TRUE(oci_config_file != nullptr); ++ ++ ++ oci_spec = oci_runtime_spec_parse_file(oci_config_file, nullptr, &err); ++ ASSERT_TRUE(oci_spec != nullptr); ++ free(err); ++ ++ check_capabilities_len(oci_spec->process->capabilities, &old_lens); ++ ++ ret = merge_caps(oci_spec, adds, adds_len, drops, drops_len); ++ ASSERT_EQ(ret, 0); ++ ++ /* Nothing dropped */ ++ validate_capabilities_len(oci_spec->process->capabilities, &old_lens, 0); ++ ++ free_oci_runtime_spec(oci_spec); ++} ++ ++TEST(merge_capability_ut, test_merge_caps_drops_existing_without_adds) ++{ ++ oci_runtime_spec *oci_spec = nullptr; ++ int ret = 0; ++ char *err = nullptr; ++ struct capabilities_lens old_lens = { 0 }; ++ char *oci_config_file = nullptr; ++ const char *adds[] = {}; ++ /* Below capabilities are in the oci_config_file */ ++ const char *drops[] = { "CHOWN", "MKNOD" }; ++ size_t adds_len = sizeof(adds) / sizeof(adds[0]); ++ size_t drops_len = sizeof(drops) / sizeof(drops[0]); ++ ++ oci_config_file = json_path(OCI_RUNTIME_SPEC_FILE); ++ ASSERT_TRUE(oci_config_file != nullptr); ++ ++ ++ oci_spec = oci_runtime_spec_parse_file(oci_config_file, nullptr, &err); ++ ASSERT_TRUE(oci_spec != nullptr); ++ free(err); ++ ++ check_capabilities_len(oci_spec->process->capabilities, &old_lens); ++ ++ ret = merge_caps(oci_spec, adds, adds_len, drops, drops_len); ++ ASSERT_EQ(ret, 0); ++ ++ /* All dropped */ ++ validate_capabilities_len(oci_spec->process->capabilities, &old_lens, adds_len - drops_len); ++ ++ free_oci_runtime_spec(oci_spec); ++} ++ ++TEST(merge_capability_ut, test_merge_caps_adds_drops) ++{ ++ oci_runtime_spec *oci_spec = nullptr; ++ int ret = 0; ++ char *err = nullptr; ++ struct capabilities_lens old_lens = { 0 }; ++ char *oci_config_file = nullptr; ++ /* All of below capabilities are not in oci_config_file */ ++ const char *adds[] = { "NET_ADMIN", "SYS_ADMIN", "SYS_TTY_CONFIG", "SYS_PTRACE" }; ++ const char *drops[] = { "SYS_TTY_CONFIG", "SYS_PTRACE" }; ++ size_t adds_len = sizeof(adds) / sizeof(adds[0]); ++ size_t drops_len = sizeof(drops) / sizeof(drops[0]); ++ ++ oci_config_file = json_path(OCI_RUNTIME_SPEC_FILE); ++ ASSERT_TRUE(oci_config_file != nullptr); ++ ++ ++ oci_spec = oci_runtime_spec_parse_file(oci_config_file, nullptr, &err); ++ ASSERT_TRUE(oci_spec != nullptr); ++ free(err); ++ ++ check_capabilities_len(oci_spec->process->capabilities, &old_lens); ++ ++ ret = merge_caps(oci_spec, adds, adds_len, drops, drops_len); ++ ASSERT_EQ(ret, 0); ++ ++ validate_capabilities_len(oci_spec->process->capabilities, &old_lens, adds_len - drops_len); ++ ++ free_oci_runtime_spec(oci_spec); ++} ++ ++TEST(merge_capability_ut, test_merge_caps_adds_all_without_drops) ++{ ++ oci_runtime_spec *oci_spec = nullptr; ++ int ret = 0; ++ char *err = nullptr; ++ struct capabilities_lens old_lens = { 0 }; ++ char *oci_config_file = nullptr; ++ /* NET_ADMIN is in all */ ++ const char *adds[] = { "ALL", "NET_ADMIN" }; ++ const char *drops[] = {}; ++ size_t adds_len = sizeof(adds) / sizeof(adds[0]); ++ size_t drops_len = sizeof(drops) / sizeof(drops[0]); ++ size_t all_caps_len = 0; ++ util_get_all_caps(&all_caps_len); ++ ++ oci_config_file = json_path(OCI_RUNTIME_SPEC_FILE); ++ ASSERT_TRUE(oci_config_file != nullptr); ++ ++ oci_spec = oci_runtime_spec_parse_file(oci_config_file, nullptr, &err); ++ ASSERT_TRUE(oci_spec != nullptr); ++ free(err); ++ ++ check_capabilities_len(oci_spec->process->capabilities, &old_lens); ++ ++ ret = merge_caps(oci_spec, adds, adds_len, drops, drops_len); ++ ASSERT_EQ(ret, 0); ++ ++ ASSERT_EQ(oci_spec->process->capabilities->bounding_len, all_caps_len); ++ ASSERT_EQ(oci_spec->process->capabilities->effective_len, all_caps_len); ++ ASSERT_EQ(oci_spec->process->capabilities->permitted_len, all_caps_len); ++ ++ free_oci_runtime_spec(oci_spec); ++} ++ ++TEST(merge_capability_ut, test_merge_caps_adds_all_and_extra_without_drops) ++{ ++ oci_runtime_spec *oci_spec = nullptr; ++ int ret = 0; ++ char *err = nullptr; ++ struct capabilities_lens old_lens = { 0 }; ++ char *oci_config_file = nullptr; ++ /* ABC is not in all */ ++ const char *adds[] = { "ALL", "ABC" }; ++ const char *drops[] = {}; ++ size_t adds_len = sizeof(adds) / sizeof(adds[0]); ++ size_t drops_len = sizeof(drops) / sizeof(drops[0]); ++ size_t all_caps_len = 0; ++ util_get_all_caps(&all_caps_len); ++ ++ oci_config_file = json_path(OCI_RUNTIME_SPEC_FILE); ++ ASSERT_TRUE(oci_config_file != nullptr); ++ ++ oci_spec = oci_runtime_spec_parse_file(oci_config_file, nullptr, &err); ++ ASSERT_TRUE(oci_spec != nullptr); ++ free(err); ++ ++ check_capabilities_len(oci_spec->process->capabilities, &old_lens); ++ ++ ret = merge_caps(oci_spec, adds, adds_len, drops, drops_len); ++ ASSERT_EQ(ret, 0); ++ ++ ASSERT_EQ(oci_spec->process->capabilities->bounding_len, all_caps_len + 1); ++ ASSERT_EQ(oci_spec->process->capabilities->effective_len, all_caps_len + 1); ++ ASSERT_EQ(oci_spec->process->capabilities->permitted_len, all_caps_len + 1); ++ ++ free_oci_runtime_spec(oci_spec); ++} ++ ++TEST(merge_capability_ut, test_merge_caps_adds_all_drops_all) ++{ ++ oci_runtime_spec *oci_spec = nullptr; ++ int ret = 0; ++ char *err = nullptr; ++ struct capabilities_lens old_lens = { 0 }; ++ char *oci_config_file = nullptr; ++ /* ABC, EFG is not in all */ ++ const char *adds[] = { "ALL", "ABC", "EFG"}; ++ const char *drops[] = { "ALL", "ABC" }; ++ size_t adds_len = sizeof(adds) / sizeof(adds[0]); ++ size_t drops_len = sizeof(drops) / sizeof(drops[0]); ++ size_t all_caps_len = 0; ++ util_get_all_caps(&all_caps_len); ++ ++ oci_config_file = json_path(OCI_RUNTIME_SPEC_FILE); ++ ASSERT_TRUE(oci_config_file != nullptr); ++ ++ oci_spec = oci_runtime_spec_parse_file(oci_config_file, nullptr, &err); ++ ASSERT_TRUE(oci_spec != nullptr); ++ free(err); ++ ++ check_capabilities_len(oci_spec->process->capabilities, &old_lens); ++ ++ ret = merge_caps(oci_spec, adds, adds_len, drops, drops_len); ++ ASSERT_EQ(ret, 0); ++ ++ ASSERT_EQ(oci_spec->process->capabilities->bounding_len, 1); ++ ASSERT_EQ(oci_spec->process->capabilities->effective_len, 1); ++ ASSERT_EQ(oci_spec->process->capabilities->permitted_len, 1); ++ ++ free_oci_runtime_spec(oci_spec); ++} +diff --git a/test/specs/specs_extend/CMakeLists.txt b/test/specs/specs_extend/CMakeLists.txt +index 294690e8..bf4b378e 100644 +--- a/test/specs/specs_extend/CMakeLists.txt ++++ b/test/specs/specs_extend/CMakeLists.txt +@@ -14,6 +14,7 @@ add_executable(${EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/util_atomic.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_mount_spec.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_fs.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_cap.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/sha256/sha256.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/path.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/map/map.c +-- +2.42.0 + diff --git a/0010-2245-fix-utils_verify_ut-failure-when-remote-grpc-fu.patch b/0010-2245-fix-utils_verify_ut-failure-when-remote-grpc-fu.patch new file mode 100644 index 0000000..8a7253e --- /dev/null +++ b/0010-2245-fix-utils_verify_ut-failure-when-remote-grpc-fu.patch @@ -0,0 +1,33 @@ +From c8415e904333c99a2fcd4f8d070942b6923d44ed Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Mon, 13 Nov 2023 08:52:42 +0000 +Subject: [PATCH 10/14] !2245 fix utils_verify_ut failure when remote grpc + function is turned off * fix utils_verify_ut failure when remote grpc + function is turned off + +--- + test/cutils/utils_verify/utils_verify_ut.cc | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/test/cutils/utils_verify/utils_verify_ut.cc b/test/cutils/utils_verify/utils_verify_ut.cc +index 79670ec1..f2ff57c7 100644 +--- a/test/cutils/utils_verify/utils_verify_ut.cc ++++ b/test/cutils/utils_verify/utils_verify_ut.cc +@@ -70,12 +70,14 @@ TEST(utils_verify, test_util_validate_socket) + ASSERT_EQ(util_validate_socket("unix://./isulad"), false); + ASSERT_EQ(util_validate_socket("unix://isulad"), false); + ++#ifdef ENABLE_GRPC_REMOTE_CONNECT + ASSERT_EQ(util_validate_socket("tcp://localhost:2375"), true); + ASSERT_EQ(util_validate_socket("tcp://127.0.0.1:2375"), true); + + ASSERT_EQ(util_validate_socket("tcp://"), false); + ASSERT_EQ(util_validate_socket("tcp://127.0.0.1"), false); + ASSERT_EQ(util_validate_socket("tcp://127.0.0.1,2375"), false); ++#endif + } + + TEST(utils_verify, test_util_valid_device_mode) +-- +2.42.0 + diff --git a/0011-add-runc-attach-implement.patch b/0011-add-runc-attach-implement.patch new file mode 100644 index 0000000..088e339 --- /dev/null +++ b/0011-add-runc-attach-implement.patch @@ -0,0 +1,1312 @@ +From aaf1b46c66aa596ec718c11c4f4270e41e7b570e Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Tue, 7 Nov 2023 16:39:35 +0800 +Subject: [PATCH 11/14] add runc attach implement + +Signed-off-by: zhongtao +--- + .../connect/grpc/grpc_containers_client.cc | 9 + + src/cmd/isula/stream/attach.c | 12 +- + src/cmd/isulad-shim/common.c | 116 ++++- + src/cmd/isulad-shim/common.h | 30 ++ + src/cmd/isulad-shim/main.c | 14 + + src/cmd/isulad-shim/process.c | 453 ++++++++++++++++-- + src/cmd/isulad-shim/process.h | 7 +- + src/cmd/isulad-shim/terminal.c | 2 +- + .../executor/container_cb/execution_stream.c | 1 + + src/daemon/modules/api/runtime_api.h | 1 + + .../modules/runtime/isula/isula_rt_ops.c | 168 ++++++- + src/utils/cutils/error.h | 4 +- + 12 files changed, 755 insertions(+), 62 deletions(-) + +diff --git a/src/client/connect/grpc/grpc_containers_client.cc b/src/client/connect/grpc/grpc_containers_client.cc +index 2dd73100..bcb1e8da 100644 +--- a/src/client/connect/grpc/grpc_containers_client.cc ++++ b/src/client/connect/grpc/grpc_containers_client.cc +@@ -1394,6 +1394,8 @@ public: + auto run(const struct isula_attach_request *request, struct isula_attach_response *response) -> int override + { + ClientContext context; ++ bool detach = false; ++ std::string attach_detach_msg = "read escape sequence"; + + if (set_custom_header_metadata(context, request) != 0) { + ERROR("Failed to translate request to grpc"); +@@ -1415,6 +1417,9 @@ public: + break; + } + if (!stream_response.stdout().empty()) { ++ if (strcmp(stream_response.stdout().c_str(), attach_detach_msg.c_str()) == 0) { ++ detach = true; ++ } + std::cout << stream_response.stdout() << std::flush; + } + if (!stream_response.stderr().empty()) { +@@ -1437,6 +1442,10 @@ public: + response->cc = ISULAD_ERR_EXEC; + } + ++ if (detach) { ++ response->server_errono = ISULAD_INFO_DETACH; ++ } ++ + out: + if (request->attach_stdin) { + pthread_cancel(writer.native_handle()); +diff --git a/src/cmd/isula/stream/attach.c b/src/cmd/isula/stream/attach.c +index ff49af92..b61c9350 100644 +--- a/src/cmd/isula/stream/attach.c ++++ b/src/cmd/isula/stream/attach.c +@@ -37,6 +37,7 @@ + #include "connect.h" + #include "constants.h" + #include "client_helpers.h" ++#include "error.h" + #ifndef GRPC_CONNECTOR + #include "client_console.h" + #endif +@@ -70,8 +71,10 @@ static int check_tty(bool tty, struct termios *oldtios, bool *reset_tty) + } + *reset_tty = true; + } else { +- INFO("the input device is not a TTY"); +- return 0; ++ // if it is trying to attach to a container TTY ++ // from a non-TTY client input stream, returns -1. ++ COMMAND_ERROR("the input device is not a TTY"); ++ return -1; + } + + return 0; +@@ -353,6 +356,7 @@ static int client_attach(struct client_arguments *args, uint32_t *exit_code) + #endif + + config = get_connect_config(args); ++ // Obtain the container's real exit code by waiting for the container to stop. + container_wait_thread(args, exit_code, &sem_exited); + ret = ops->container.attach(&request, response, &config); + if (ret != 0) { +@@ -374,7 +378,9 @@ static int client_attach(struct client_arguments *args, uint32_t *exit_code) + + if (sem_timedwait(&sem_exited, &ts) != 0) { + if (errno == ETIMEDOUT) { +- COMMAND_ERROR("Wait container status timeout."); ++ if (response->server_errono != ISULAD_INFO_DETACH) { ++ INFO("Wait container stopped status timeout."); ++ } + } else { + CMD_SYSERROR("Failed to wait sem"); + } +diff --git a/src/cmd/isulad-shim/common.c b/src/cmd/isulad-shim/common.c +index 781dc004..48d266dc 100644 +--- a/src/cmd/isulad-shim/common.c ++++ b/src/cmd/isulad-shim/common.c +@@ -33,16 +33,26 @@ + #include + + int g_log_fd = -1; ++int g_attach_log_fd = -1; + + int init_shim_log(void) + { +- g_log_fd = open_no_inherit(SHIM_LOG_NAME, O_CREAT | O_WRONLY | O_APPEND | O_SYNC, 0640); ++ g_log_fd = open_no_inherit(SHIM_LOG_NAME, O_CREAT | O_WRONLY | O_APPEND | O_SYNC, LOG_FILE_MODE); + if (g_log_fd < 0) { + return SHIM_ERR; + } + return SHIM_OK; + } + ++int init_attach_log(void) ++{ ++ g_attach_log_fd = open_no_inherit(ATTACH_LOG_NAME, O_CREAT | O_WRONLY | O_APPEND | O_SYNC, LOG_FILE_MODE); ++ if (g_attach_log_fd < 0) { ++ return SHIM_ERR; ++ } ++ return SHIM_OK; ++} ++ + void signal_routine(int sig) + { + switch (sig) { +@@ -162,11 +172,24 @@ int generate_random_str(char *id, size_t len) + return SHIM_OK; + } + +-void write_message(const char *level, const char *fmt, ...) +-{ + #define MAX_MSG_JSON_TEMPLATE 32 + #define MAX_MESSAGE_CONTENT_LEN 128 + #define MAX_MESSAGE_LEN (MAX_MSG_JSON_TEMPLATE + MAX_MESSAGE_CONTENT_LEN) ++ ++static void format_log_msg(const char *level, const char *buf, char *msg, int max_message_len) ++{ ++ time_t current_time = time(NULL); ++ struct tm *local_time = localtime(¤t_time); ++ char time_str[20]; ++ ++ strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", local_time); ++ ++ (void)snprintf(msg, max_message_len - 1, "{\"time\": \"%s\", \"level\": \"%s\", \"msg\": \"%s\"}\n", time_str, level, ++ buf); ++} ++ ++void write_message(const char *level, const char *fmt, ...) ++{ + if (g_log_fd < 0) { + return; + } +@@ -183,15 +206,31 @@ void write_message(const char *level, const char *fmt, ...) + return; + } + +- nwrite = snprintf(msg, MAX_MESSAGE_LEN - 1, "{\"level\": \"%s\", \"msg\": \"%s\"}\n", level, buf); +- if (nwrite < 0 || (size_t)nwrite >= (MAX_MESSAGE_LEN - 1)) { ++ format_log_msg(level, buf, msg, MAX_MESSAGE_CONTENT_LEN); ++ ++ (void)isula_file_total_write_nointr(g_log_fd, msg, strlen(msg)); ++} ++ ++void write_attach_message(const char *level, const char *fmt, ...) ++{ ++ char buf[MAX_MESSAGE_CONTENT_LEN] = { 0 }; ++ char msg[MAX_MESSAGE_LEN] = { 0 }; ++ int nwrite = -1; ++ ++ if (g_attach_log_fd < 0) { + return; + } +- +- nwrite = isula_file_total_write_nointr(g_log_fd, msg, strlen(msg)); +- if (nwrite < 0 || (size_t)nwrite != strlen(msg)) { ++ va_list arg_list; ++ va_start(arg_list, fmt); ++ nwrite = vsnprintf(buf, MAX_MESSAGE_CONTENT_LEN, fmt, arg_list); ++ va_end(arg_list); ++ if (nwrite < 0) { + return; + } ++ ++ format_log_msg(level, buf, msg, MAX_MESSAGE_CONTENT_LEN); ++ ++ (void)isula_file_total_write_nointr(g_attach_log_fd, msg, strlen(msg)); + } + + /* note: This function can only read small text file. */ +@@ -272,3 +311,64 @@ int open_no_inherit(const char *path, int flag, mode_t mode) + + return fd; + } ++ ++/* judge the fd whether is attach fifo */ ++struct isula_linked_list *get_attach_fifo_item(int fd, struct isula_linked_list *list) ++{ ++ struct isula_linked_list *it = NULL; ++ struct isula_linked_list *next = NULL; ++ ++ if (fd <= 0 || list == NULL || isula_linked_list_empty(list)) { ++ return it; ++ } ++ ++ isula_linked_list_for_each_safe(it, list, next) { ++ struct shim_fifos_fd *elem = (struct shim_fifos_fd *)it->elem; ++ if (elem == NULL) { ++ continue; ++ } ++ if (elem->in_fd == fd) { ++ return it; ++ } ++ if (elem->out_fd == fd) { ++ return it; ++ } ++ if (elem->err_fd == fd) { ++ return it; ++ } ++ } ++ ++ return it; ++} ++ ++void free_shim_fifos_fd(struct shim_fifos_fd *item) ++{ ++ if (item == NULL) { ++ return; ++ } ++ if (item->in_fifo != NULL) { ++ free(item->in_fifo); ++ item->in_fifo = NULL; ++ } ++ if (item->out_fifo != NULL) { ++ free(item->out_fifo); ++ item->out_fifo = NULL; ++ } ++ if (item->err_fifo != NULL) { ++ free(item->err_fifo); ++ item->err_fifo = NULL; ++ } ++ if (item->in_fd >= 0) { ++ close(item->in_fd); ++ item->in_fd = -1; ++ } ++ if (item->out_fd >= 0) { ++ close(item->out_fd); ++ item->out_fd = -1; ++ } ++ if (item->err_fd >= 0) { ++ close(item->err_fd); ++ item->err_fd = -1; ++ } ++ free(item); ++} +\ No newline at end of file +diff --git a/src/cmd/isulad-shim/common.h b/src/cmd/isulad-shim/common.h +index 55efdc28..2020a799 100644 +--- a/src/cmd/isulad-shim/common.h ++++ b/src/cmd/isulad-shim/common.h +@@ -21,6 +21,7 @@ + #include + #include + #include ++#include + + #ifdef __cplusplus + extern "C" { +@@ -59,8 +60,22 @@ extern "C" { + #define CONTAINER_ACTION_REBOOT 129 + #define CONTAINER_ACTION_SHUTDOWN 130 + ++#define ATTACH_SOCKET "attach_socket.sock" ++#define ATTACH_LOG_NAME "attach-log.json" ++#define ATTACH_DETACH_MSG "read escape sequence" ++#define MAX_ATTACH_NUM 16 ++ ++#define CTRL_Q 0x11 // ASCII code control character ctrl + Q ++ ++#define LOG_FILE_MODE 0600 ++ ++#define SOCKET_DIRECTORY_MODE 0600 ++#define ATTACH_FIFOPATH_MODE 0600 ++ + int init_shim_log(void); + ++int init_attach_log(void); ++ + void signal_routine(int sig); + + /** +@@ -90,18 +105,33 @@ void signal_routine(int sig); + } \ + } while (0) + ++struct shim_fifos_fd { ++ char *in_fifo; ++ char *out_fifo; ++ char *err_fifo; ++ int in_fd; ++ int out_fd; ++ int err_fd; ++}; ++ + char *read_text_file(const char *path); + + int cmd_combined_output(const char *binary, const char *params[], void *output, int *output_len); + + void write_message(const char *level, const char *fmt, ...); + ++void write_attach_message(const char *level, const char *fmt, ...); ++ + int generate_random_str(char *id, size_t len); + + void close_fd(int *pfd); + + int open_no_inherit(const char *path, int flag, mode_t mode); + ++struct isula_linked_list *get_attach_fifo_item(int fd, struct isula_linked_list *list); ++ ++void free_shim_fifos_fd(struct shim_fifos_fd *item); ++ + #ifdef __cplusplus + } + #endif +diff --git a/src/cmd/isulad-shim/main.c b/src/cmd/isulad-shim/main.c +index 454011d0..deb07271 100644 +--- a/src/cmd/isulad-shim/main.c ++++ b/src/cmd/isulad-shim/main.c +@@ -145,6 +145,20 @@ int main(int argc, char **argv) + } + } + ++ if (p->state->attach_socket != NULL) { ++ ret = prepare_attach_socket(p); ++ if (ret != SHIM_OK) { ++ write_message(ERR_MSG, "failed to prepare attach socket:%d", ret); ++ exit(EXIT_FAILURE); ++ } ++ ++ ret = init_attach_log(); ++ if (ret != SHIM_OK) { ++ write_message(ERR_MSG, "failed to init shim attach log"); ++ exit(EXIT_FAILURE); ++ } ++ } ++ + /* start epoll for io copy */ + ret = process_io_start(p, &tid_epoll); + if (ret != SHIM_OK) { +diff --git a/src/cmd/isulad-shim/process.c b/src/cmd/isulad-shim/process.c +index 40908102..187067d2 100644 +--- a/src/cmd/isulad-shim/process.c ++++ b/src/cmd/isulad-shim/process.c +@@ -19,20 +19,22 @@ + #include + #include + #include ++#include ++#include ++#include // IWYU pragma: keep ++#include ++#include + #include + #include + #include +-#include + #include + #include + #include + #include +-#include +-#include + #include // IWYU pragma: keep +-#include // IWYU pragma: keep + #include + #include ++#include + + #include + #include +@@ -42,6 +44,8 @@ + #include + #include + #include ++#include ++#include + + #include "common.h" + #include "terminal.h" +@@ -57,7 +61,7 @@ static shim_client_process_state *load_process() + + p_state = shim_client_process_state_parse_file("process.json", NULL, &err); + if (p_state == NULL) { +- write_message(ERR_MSG, "parse process state failed"); ++ write_message(ERR_MSG, "parse process state failed: %s", err); + } + /* "err" will definitely be allocated memory in the function above */ + free(err); +@@ -168,6 +172,99 @@ static int sync_exit_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr + return EPOLL_LOOP_HANDLE_CLOSE; + } + ++static bool fifo_exists(const char *path) ++{ ++ struct stat sb; ++ int ret; ++ ++ ret = stat(path, &sb); ++ if (ret < 0) { ++ // could be something other than exist, just return false ++ return false; ++ } ++ ++ return S_ISFIFO(sb.st_mode); ++} ++ ++static int add_attach_terminal_fifos(const char *in, const char *out, const char *err, int *input_fd, process_t *p) ++{ ++ __isula_auto_close int fifofd_in = -1; ++ __isula_auto_close int fifofd_out = -1; ++ __isula_auto_close int fifofd_err = -1; ++ struct shim_fifos_fd *fifos = NULL; ++ struct isula_linked_list *node = NULL; ++ ++ bool invalid = (in != NULL && !fifo_exists(in)) || (out != NULL && !fifo_exists(out)) || (err != NULL && ++ !fifo_exists(err)); ++ if (invalid) { ++ write_attach_message(ERR_MSG, "File %s or %s or %s does not refer to a FIFO", in, out, err); ++ return -1; ++ } ++ ++ if (in != NULL) { ++ fifofd_in = isula_file_open(in, O_RDONLY | O_NONBLOCK | O_CLOEXEC, 0); ++ if (fifofd_in < 0) { ++ write_attach_message(ERR_MSG, "Failed to open FIFO: %s", in); ++ return -1; ++ } ++ } ++ ++ if (out != NULL) { ++ fifofd_out = isula_file_open(out, O_WRONLY | O_NONBLOCK | O_CLOEXEC, 0); ++ if (fifofd_out < 0) { ++ write_attach_message(ERR_MSG, "Failed to open FIFO: %s", out); ++ return -1; ++ } ++ } ++ ++ if (err != NULL) { ++ fifofd_err = isula_file_open(err, O_WRONLY | O_NONBLOCK | O_CLOEXEC, 0); ++ if (fifofd_err < 0) { ++ write_attach_message(ERR_MSG, "Failed to open FIFO: %s", err); ++ return -1; ++ } ++ } ++ ++ fifos = isula_common_calloc_s(sizeof(*fifos)); ++ if (fifos == NULL) { ++ write_attach_message(ERR_MSG, "Out of memory"); ++ goto err_out; ++ } ++ ++ fifos->in_fifo = isula_strdup_s(in); ++ fifos->out_fifo = isula_strdup_s(out); ++ fifos->err_fifo = isula_strdup_s(err); ++ ++ fifos->in_fd = isula_transfer_fd(fifofd_in); ++ fifos->out_fd = isula_transfer_fd(fifofd_out); ++ fifos->err_fd = isula_transfer_fd(fifofd_err); ++ node = isula_common_calloc_s(sizeof(struct isula_linked_list)); ++ if (node == NULL) { ++ write_attach_message(ERR_MSG, "Out of memory"); ++ goto err_out; ++ } ++ ++ node->elem = fifos; ++ isula_linked_list_add(p->attach_fifos, node); ++ ++ if (input_fd != NULL) { ++ *input_fd = fifos->in_fd; ++ } ++ ++ return 0; ++err_out: ++ free_shim_fifos_fd(fifos); ++ return -1; ++} ++ ++static void remove_attach_terminal_fifos(isula_epoll_descr_t *descr, struct isula_linked_list *item) ++{ ++ struct shim_fifos_fd *elem = (struct shim_fifos_fd *)item->elem; ++ isula_epoll_remove_handler(descr, elem->in_fd); ++ isula_linked_list_del(item); ++ free_shim_fifos_fd(elem); ++} ++ + static int stdin_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t *descr) + { + process_t *p = (process_t *)cbdata; +@@ -210,6 +307,57 @@ static int stdin_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t * + return EPOLL_LOOP_HANDLE_CONTINUE; + } + ++static int attach_stdin_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t *descr) ++{ ++ process_t *p = (process_t *)cbdata; ++ int r_count = 0; ++ int w_count = 0; ++ int *fd_to = NULL; ++ struct isula_linked_list *item; ++ ++ if (events & EPOLLHUP) { ++ write_message(ERR_MSG, "attach stdin %d received the EPOLLHUP event", fd); ++ goto err_out; ++ } ++ ++ if (!(events & EPOLLIN)) { ++ return EPOLL_LOOP_HANDLE_CONTINUE; ++ } ++ ++ (void)memset(p->buf, 0, DEFAULT_IO_COPY_BUF); ++ ++ r_count = isula_file_read_nointr(fd, p->buf, DEFAULT_IO_COPY_BUF); ++ if (r_count <= 0) { ++ write_message(ERR_MSG, "failed to read from attach stdin %d, error:%d", fd, SHIM_SYS_ERR(errno)); ++ goto err_out; ++ } ++ ++ if (p->state->terminal) { ++ fd_to = &(p->recv_fd); ++ } else { ++ fd_to = &(p->shim_io->in); ++ } ++ ++ if (fd_to == NULL || *fd_to == -1) { ++ return EPOLL_LOOP_HANDLE_CONTINUE; ++ } ++ w_count = isula_file_total_write_nointr(*fd_to, p->buf, r_count); ++ if (w_count < 0) { ++ /* When any error occurs, set the write fd -1 */ ++ write_message(WARN_MSG, "write in_fd %d error:%d", *fd_to, SHIM_SYS_ERR(errno)); ++ close(*fd_to); ++ *fd_to = -1; ++ } ++ ++ return EPOLL_LOOP_HANDLE_CONTINUE; ++err_out: ++ item = get_attach_fifo_item(fd, p->attach_fifos); ++ if (item != NULL && item->elem != NULL) { ++ remove_attach_terminal_fifos(descr, item); ++ } ++ return EPOLL_LOOP_HANDLE_CONTINUE; ++} ++ + static int stdout_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t *descr) + { + process_t *p = (process_t *)cbdata; +@@ -237,16 +385,29 @@ static int stdout_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t + + shim_write_container_log_file(p->terminal, STDID_OUT, p->buf, r_count); + +- if (p->isulad_io->out == -1) { ++ if (p->isulad_io->out != -1) { ++ w_count = isula_file_total_write_nointr(p->isulad_io->out, p->buf, r_count); ++ if (w_count < 0) { ++ /* When any error occurs, set the write fd -1 */ ++ write_message(WARN_MSG, "write out_fd %d error:%d", p->isulad_io->out, SHIM_SYS_ERR(errno)); ++ close(p->isulad_io->out); ++ p->isulad_io->out = -1; ++ } ++ } ++ ++ if (isula_linked_list_empty(p->attach_fifos)) { + return EPOLL_LOOP_HANDLE_CONTINUE; + } + +- w_count = isula_file_total_write_nointr(p->isulad_io->out, p->buf, r_count); +- if (w_count < 0) { +- /* When any error occurs, set the write fd -1 */ +- write_message(WARN_MSG, "write out_fd %d error:%d", p->isulad_io->out, SHIM_SYS_ERR(errno)); +- close(p->isulad_io->out); +- p->isulad_io->out = -1; ++ struct isula_linked_list *it = NULL; ++ struct isula_linked_list *next = NULL; ++ ++ isula_linked_list_for_each_safe(it, p->attach_fifos, next) { ++ struct shim_fifos_fd *elem = (struct shim_fifos_fd *)it->elem; ++ w_count = isula_file_total_write_nointr(elem->out_fd, p->buf, r_count); ++ if (w_count < 0) { ++ remove_attach_terminal_fifos(descr, it); ++ } + } + + return EPOLL_LOOP_HANDLE_CONTINUE; +@@ -279,16 +440,29 @@ static int stderr_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t + + shim_write_container_log_file(p->terminal, STDID_ERR, p->buf, r_count); + +- if (p->isulad_io->err == -1) { ++ if (p->isulad_io->err != -1) { ++ w_count = isula_file_total_write_nointr(p->isulad_io->err, p->buf, r_count); ++ if (w_count < 0) { ++ /* When any error occurs, set the write fd -1 */ ++ write_message(WARN_MSG, "write err_fd %d error:%d", p->isulad_io->err, SHIM_SYS_ERR(errno)); ++ close(p->isulad_io->err); ++ p->isulad_io->err = -1; ++ } ++ } ++ ++ if (isula_linked_list_empty(p->attach_fifos)) { + return EPOLL_LOOP_HANDLE_CONTINUE; + } + +- w_count = isula_file_total_write_nointr(p->isulad_io->err, p->buf, r_count); +- if (w_count < 0) { +- /* When any error occurs, set the write fd -1 */ +- write_message(WARN_MSG, "write err_fd %d error:%d", p->isulad_io->err, SHIM_SYS_ERR(errno)); +- close(p->isulad_io->err); +- p->isulad_io->err = -1; ++ struct isula_linked_list *it = NULL; ++ struct isula_linked_list *next = NULL; ++ ++ isula_linked_list_for_each_safe(it, p->attach_fifos, next) { ++ struct shim_fifos_fd *elem = (struct shim_fifos_fd *)it->elem; ++ w_count = isula_file_total_write_nointr(elem->out_fd, p->buf, r_count); ++ if (w_count < 0) { ++ remove_attach_terminal_fifos(descr, it); ++ } + } + + return EPOLL_LOOP_HANDLE_CONTINUE; +@@ -326,6 +500,159 @@ static int resize_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t + return EPOLL_LOOP_HANDLE_CONTINUE; + } + ++static bool attach_fifopath_security_check(process_t *p, const char *fifopath) ++{ ++ struct stat st = { 0 }; ++ char real_path[PATH_MAX] = { 0 }; ++ ++ if (isula_validate_absolute_path(fifopath) != 0) { ++ write_attach_message(ERR_MSG, "attach fifo path \"%s\" must be an valid absolute path", fifopath); ++ return false; ++ } ++ ++ if (realpath(fifopath, real_path) == NULL) { ++ write_attach_message(ERR_MSG, "Failed to get realpath for '%s': %s.", real_path, SHIM_SYS_ERR(errno)); ++ return false; ++ } ++ ++ if (!isula_has_prefix(real_path, p->workdir)) { ++ write_attach_message(ERR_MSG, "attach fifo path \"%s\" must be under the state path", real_path, p->workdir); ++ return false; ++ } ++ ++ if (lstat(real_path, &st) != 0) { ++ write_attach_message(ERR_MSG, "Failed to lstat %s : %s", real_path, SHIM_SYS_ERR(errno)); ++ return false; ++ } ++ ++ if (!S_ISFIFO(st.st_mode)) { ++ write_attach_message(ERR_MSG, "attach fifo path \"%s\" must be an FIFO", real_path); ++ return false; ++ } ++ ++ if ((st.st_mode & 0777) != ATTACH_FIFOPATH_MODE) { ++ write_attach_message(ERR_MSG, "attach fifo path \"%s\" permission invalid", real_path); ++ return false; ++ } ++ ++ if (st.st_uid != 0) { ++ write_attach_message(ERR_MSG, "attach fifo path \"%s\" uid invalid", real_path); ++ return false; ++ } ++ ++ return true; ++} ++ ++// attach_cb needs to read the content from communication fd and parse it. ++// at the same time, it also needs to establish a connection between the attach fd and the container fd. ++// 1. if it fails, it needs to write an error message to attach log file, ++// and write -1 to connection fd to let isulad know that it has failed. ++// 2. if it succeeds, write 0 to let isulad know that it is ready. ++// attach_cb returns EPOLL_LOOP_HANDLE_CONTINUE regardless of success or failure, ++// because whether the attach operation is successful or not does not affect the first process of the container. ++static int attach_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t *descr) ++{ ++ process_t *p = (process_t *)cbdata; ++ int r_count = 0; ++ char tmp_buf[BUFSIZ + 1] = { 0 }; ++ char *in = NULL, *out = NULL, *err = NULL; ++ int fifofd_in = -1; ++ isula_string_array *tmp_str_array = NULL; ++ int ret = 0; ++ // attach execution return value ++ int status = -1; ++ bool valid = true; ++ ++ // after receiving the event that isulad closes the connection, ++ // close the communication fd and remove it from epoll. ++ if (events & EPOLLHUP) { ++ close(fd); ++ isula_epoll_remove_handler(descr, fd); ++ return EPOLL_LOOP_HANDLE_CONTINUE; ++ } ++ ++ if (!(events & EPOLLIN)) { ++ return EPOLL_LOOP_HANDLE_CONTINUE; ++ } ++ ++ r_count = isula_file_read_nointr(fd, tmp_buf, sizeof(tmp_buf) - 1); ++ if (r_count <= 0) { ++ write_attach_message(ERR_MSG, "Failed to read msg from attach conn fd"); ++ goto out; ++ } ++ ++ // limit the number of attach connections to MAX_ATTACH_NUM ++ if (isula_linked_list_len(p->attach_fifos) >= MAX_ATTACH_NUM) { ++ write_attach_message(ERR_MSG, "The number of attach connections exceeds the limit:%d, and this connection is rejected.", ++ MAX_ATTACH_NUM); ++ goto out; ++ } ++ ++ tmp_str_array = isula_string_split_to_multi(tmp_buf, ' '); ++ if (tmp_str_array->len != 3) { ++ write_attach_message(ERR_MSG, "Invalid attach msg from isulad"); ++ goto out; ++ } ++ ++ for (int i = 0; i < tmp_str_array->len; i++) { ++ valid = valid && attach_fifopath_security_check(p, tmp_str_array->items[i]); ++ } ++ ++ if (!valid) { ++ write_attach_message(ERR_MSG, "Invalid attach fifo path from isulad"); ++ goto out; ++ } ++ ++ in = tmp_str_array->items[0]; ++ out = tmp_str_array->items[1]; ++ err = tmp_str_array->items[2]; ++ ++ if (add_attach_terminal_fifos(in, out, err, &fifofd_in, p) < 0) { ++ write_attach_message(ERR_MSG, "Failed to add attach terminal fifos"); ++ goto out; ++ } ++ ++ // attach stdin --> container stdin ++ ret = isula_epoll_add_handler(descr, fifofd_in, attach_stdin_cb, p); ++ if (ret != SHIM_OK) { ++ write_attach_message(ERR_MSG, "add fifofd_in fd %d to epoll loop failed:%d", fifofd_in, SHIM_SYS_ERR(errno)); ++ struct isula_linked_list *item = get_attach_fifo_item(fd, p->attach_fifos); ++ if (item != NULL && item->elem != NULL) { ++ remove_attach_terminal_fifos(descr, item); ++ } ++ goto out; ++ } ++ ++ status = 0; ++out: ++ isula_string_array_free(tmp_str_array); ++ (void)isula_file_write_nointr(fd, &status, sizeof(int)); ++ return EPOLL_LOOP_HANDLE_CONTINUE; ++} ++ ++// do_attach_socket_accept returns EPOLL_LOOP_HANDLE_CONTINUE regardless of success or failure, ++// because whether the attach operation is successful or not does not affect the first process of the container. ++static int do_attach_socket_accept(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t *descr) ++{ ++ process_t *p = (process_t *)cbdata; ++ int conn_fd = -1; ++ int ret = SHIM_ERR; ++ ++ conn_fd = accept(p->attach_socket_fd, NULL, NULL); ++ if (conn_fd < 0) { ++ write_attach_message(ERR_MSG, "accept from fd %d failed:%d", p->attach_socket_fd, SHIM_SYS_ERR(errno)); ++ return EPOLL_LOOP_HANDLE_CONTINUE; ++ } ++ ++ ret = isula_epoll_add_handler(descr, conn_fd, attach_cb, p); ++ if (ret != SHIM_OK) { ++ write_attach_message(ERR_MSG, "add recv_fd %d to epoll loop failed:%d", conn_fd, SHIM_SYS_ERR(errno)); ++ close(conn_fd); ++ return EPOLL_LOOP_HANDLE_CONTINUE; ++ } ++ return EPOLL_LOOP_HANDLE_CONTINUE; ++} ++ + static int task_console_accept(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t *descr) + { + process_t *p = (process_t *)cbdata; +@@ -399,6 +726,7 @@ static void stdio_release(int (*stdio_fd)[2]) + for (j = 0; j < 2; j++) { + if (stdio_fd[i][j] > 0) { + close(stdio_fd[i][j]); ++ stdio_fd[i][j] = -1; + } + } + } +@@ -568,24 +896,6 @@ static int open_generic_io(process_t *p, isula_epoll_descr_t *descr) + return SHIM_OK; + } + +-static int set_non_block(int fd) +-{ +- int flag = -1; +- int ret = SHIM_ERR; +- +- flag = fcntl(fd, F_GETFL, 0); +- if (flag < 0) { +- return SHIM_ERR; +- } +- +- ret = fcntl(fd, F_SETFL, flag | O_NONBLOCK); +- if (ret != 0) { +- return SHIM_ERR; +- } +- +- return SHIM_OK; +-} +- + /* + std_id: channel type + isulad_stdio: one side of the isulad fifo file +@@ -623,6 +933,14 @@ static void *io_epoll_loop(void *data) + exit(EXIT_FAILURE); + } + ++ if (p->state->attach_socket != NULL) { ++ ret = isula_epoll_add_handler(&descr, p->attach_socket_fd, do_attach_socket_accept, p); ++ if (ret != SHIM_OK) { ++ write_message(ERR_MSG, "add attach_socket_fd %d to epoll loop failed:%d", p->attach_socket_fd, SHIM_SYS_ERR(errno)); ++ exit(EXIT_FAILURE); ++ } ++ } ++ + if (p->state->terminal) { + ret = open_terminal_io(p, &descr); + } else { +@@ -651,7 +969,7 @@ static void *io_epoll_loop(void *data) + } + + if (fd_out > 0) { +- ret = set_non_block(fd_out); ++ ret = isula_set_non_block(fd_out); + if (ret != SHIM_OK) { + write_message(ERR_MSG, "set fd %d non_block failed:%d", fd_out, SHIM_SYS_ERR(errno)); + exit(EXIT_FAILURE); +@@ -666,7 +984,7 @@ static void *io_epoll_loop(void *data) + } + + if (fd_err > 0) { +- ret = set_non_block(fd_err); ++ ret = isula_set_non_block(fd_err); + if (ret != SHIM_OK) { + write_message(ERR_MSG, "set fd %d non_block failed:%d", fd_err, SHIM_SYS_ERR(errno)); + exit(EXIT_FAILURE); +@@ -807,15 +1125,19 @@ failure: + if (p->isulad_io != NULL) { + if (p->isulad_io->in > 0) { + close(p->isulad_io->in); ++ p->isulad_io->in = -1; + } + if (p->isulad_io->out > 0) { + close(p->isulad_io->out); ++ p->isulad_io->out = -1; + } + if (p->isulad_io->err > 0) { + close(p->isulad_io->err); ++ p->isulad_io->err = -1; + } + if (p->isulad_io->resize > 0) { + close(p->isulad_io->resize); ++ p->isulad_io->resize = -1; + } + free(p->isulad_io); + p->isulad_io = NULL; +@@ -937,6 +1259,13 @@ process_t *new_process(char *id, char *bundle, char *runtime) + goto failure; + } + ++ p->attach_fifos = isula_common_calloc_s(sizeof(struct isula_linked_list)); ++ if (p->attach_fifos == NULL) { ++ goto failure; ++ } ++ ++ isula_linked_list_init(p->attach_fifos); ++ + return p; + + failure: +@@ -1368,3 +1697,49 @@ int process_signal_handle_routine(process_t *p, const pthread_t tid_epoll, const + (void)isula_file_write_nointr(STDOUT_FILENO, &status, sizeof(int)); + return SHIM_OK; + } ++ ++int prepare_attach_socket(process_t *p) ++{ ++ struct sockaddr_un addr; ++ int ret = -1; ++ ++ if (strlen(p->state->attach_socket) >= sizeof(addr.sun_path)) { ++ write_message(ERR_MSG, "Invalid attach socket path: %s", p->state->attach_socket); ++ return SHIM_ERR; ++ } ++ ++ p->attach_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); ++ if (p->attach_socket_fd < 0) { ++ write_message(ERR_MSG, "Failed to create socket:%d", SHIM_SYS_ERR(errno)); ++ return SHIM_ERR; ++ } ++ ++ (void)memset(&addr, 0, sizeof(addr)); ++ addr.sun_family = AF_UNIX; ++ (void)strncpy(addr.sun_path, p->state->attach_socket, sizeof(addr.sun_path) - 1); ++ ++ ret = bind(p->attach_socket_fd, (struct sockaddr *)&addr, sizeof(addr)); ++ if (ret < 0) { ++ write_message(ERR_MSG, "bind console fd failed:%d", SHIM_SYS_ERR(errno)); ++ return SHIM_ERR; ++ } ++ ++ ret = chmod(p->state->attach_socket, SOCKET_DIRECTORY_MODE); ++ if (ret != 0) { ++ write_message(ERR_MSG, "Failed to chmod for socket: %s", p->state->attach_socket); ++ return SHIM_ERR; ++ } ++ ++ //If the backlog argument is greater than the value in ++ // /proc/sys/net/core/somaxconn, then it is silently capped to that ++ // value. Since Linux 5.4, the default in this file is 4096; in ++ // earlier kernels, the default value is 128. Before Linux 2.4.25, ++ // this limit was a hard coded value, SOMAXCONN, with the value 128. ++ // The maximum number of attach we allow here is MAX_ATTACH_NUM, so just use it directly ++ ret = listen(p->attach_socket_fd, MAX_ATTACH_NUM); ++ if (ret < 0) { ++ write_message(ERR_MSG, "listen console fd failed:%d", SHIM_SYS_ERR(errno)); ++ return SHIM_ERR; ++ } ++ return SHIM_OK; ++} +\ No newline at end of file +diff --git a/src/cmd/isulad-shim/process.h b/src/cmd/isulad-shim/process.h +index 280d9874..5607316c 100644 +--- a/src/cmd/isulad-shim/process.h ++++ b/src/cmd/isulad-shim/process.h +@@ -19,7 +19,8 @@ + #include + #include + #include +-#include "isula_libutils/shim_client_process_state.h" ++#include ++#include "isula_libutils/utils_linked_list.h" + #include "terminal.h" + + #ifdef __cplusplus +@@ -49,6 +50,7 @@ typedef struct process { + char *root_path; + int io_loop_fd; + int exit_fd; ++ int attach_socket_fd; // the server socket fd that establishes a connection with isulad + int ctr_pid; + int sync_fd; + int listen_fd; +@@ -58,6 +60,7 @@ typedef struct process { + stdio_t *stdio; // shim to on runtime side, in:r out/err: w + stdio_t *shim_io; // shim io on isulad side, in: w out/err: r + stdio_t *isulad_io; // isulad io, in:r out/err: w ++ struct isula_linked_list *attach_fifos; /* isulad: fifos used to attach teminal */ + shim_client_process_state *state; + sem_t sem_mainloop; + char *buf; +@@ -70,6 +73,8 @@ typedef struct { + + process_t* new_process(char *id, char *bundle, char *runtime); + ++int prepare_attach_socket(process_t *p); ++ + int process_io_start(process_t *p, pthread_t *tid_epoll); + int create_process(process_t *p); + int process_signal_handle_routine(process_t *p, const pthread_t tid_epoll, const uint64_t timeout); +diff --git a/src/cmd/isulad-shim/terminal.c b/src/cmd/isulad-shim/terminal.c +index 0653dc45..1c063300 100644 +--- a/src/cmd/isulad-shim/terminal.c ++++ b/src/cmd/isulad-shim/terminal.c +@@ -162,7 +162,7 @@ static int shim_json_data_write(log_terminal *terminal, const char *buf, int rea + * shouldn't happen, otherwise, discard some last bytes. + */ + nret = isula_file_total_write_nointr(terminal->fd, buf, +- terminal->log_maxsize < read_count ? terminal->log_maxsize : read_count); ++ terminal->log_maxsize < read_count ? terminal->log_maxsize : read_count); + if (nret < 0) { + ret = -1; + goto out; +diff --git a/src/daemon/executor/container_cb/execution_stream.c b/src/daemon/executor/container_cb/execution_stream.c +index 7db96b19..124dcfe2 100644 +--- a/src/daemon/executor/container_cb/execution_stream.c ++++ b/src/daemon/executor/container_cb/execution_stream.c +@@ -346,6 +346,7 @@ static int container_attach_cb(const container_attach_request *request, containe + } + + params.rootpath = cont->root_path; ++ params.state = cont->state_path; + params.stdin = fifos[0]; + params.stdout = fifos[1]; + params.stderr = fifos[2]; +diff --git a/src/daemon/modules/api/runtime_api.h b/src/daemon/modules/api/runtime_api.h +index edb33d02..3c2100f5 100644 +--- a/src/daemon/modules/api/runtime_api.h ++++ b/src/daemon/modules/api/runtime_api.h +@@ -161,6 +161,7 @@ typedef struct _rt_resume_params_t { + + typedef struct _rt_attach_params_t { + const char *rootpath; ++ const char *state; + const char *stdin; + const char *stdout; + const char *stderr; +diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c +index cb1ee26f..1787170b 100644 +--- a/src/daemon/modules/runtime/isula/isula_rt_ops.c ++++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c +@@ -18,6 +18,10 @@ + #include "isula_rt_ops.h" + #include + #include ++#include ++#include ++#include ++#include + #include + #include + #include +@@ -26,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -52,9 +57,11 @@ + + #define SHIM_BINARY "isulad-shim" + #define RESIZE_FIFO_NAME "resize_fifo" ++#define ATTACH_SOCKET "attach_socket.sock" + #define SHIM_LOG_SIZE ((BUFSIZ - 100) / 2) + #define RESIZE_DATA_SIZE 100 + #define PID_WAIT_TIME 120 ++#define ATTACH_WAIT_TIME 120 + #define SHIM_EXIT_TIMEOUT 2 + + // file name formats of cgroup resources json +@@ -223,6 +230,19 @@ static void show_shim_runtime_errlog(const char *workdir) + isulad_set_error_message(buf); + } + ++static void show_shim_attach_errlog(const char *workdir) ++{ ++ char buf[SHIM_LOG_SIZE] = { 0 }; ++ ++ if (g_isulad_errmsg != NULL) { ++ return; ++ } ++ ++ get_err_message(buf, sizeof(buf), workdir, "attach-log.json"); ++ ERROR("shim-log: %s", buf); ++ isulad_set_error_message("shim-log error:\n%s\n", buf); ++} ++ + bool rt_isula_detect(const char *runtime) + { + if (runtime != NULL && (strcasecmp(runtime, "lcr") != 0)) { +@@ -463,8 +483,9 @@ static void runtime_exec_param_init(runtime_exec_info *rei) + } + } + +-static int runtime_exec_info_init(runtime_exec_info *rei, const char *workdir, const char *root_path, const char *runtime, const char *subcmd, +- const char **opts, size_t opts_len, const char *id, char **params, size_t params_num) ++static int runtime_exec_info_init(runtime_exec_info *rei, const char *workdir, const char *root_path, ++ const char *runtime, const char *subcmd, const char **opts, size_t opts_len, const char *id, char **params, ++ size_t params_num) + { + int ret = 0; + rei->workdir = workdir; +@@ -1012,6 +1033,7 @@ int rt_isula_create(const char *id, const char *runtime, const rt_create_params_ + size_t runtime_args_len = 0; + int ret = 0; + char workdir[PATH_MAX] = { 0 }; ++ char attach_socket[PATH_MAX] = { 0 }; + shim_client_process_state p = { 0 }; + int shim_exit_code = 0; + int nret = 0; +@@ -1034,6 +1056,13 @@ int rt_isula_create(const char *id, const char *runtime, const rt_create_params_ + goto out; + } + ++ nret = snprintf(attach_socket, sizeof(attach_socket), "%s/%s", workdir, ATTACH_SOCKET); ++ if (nret < 0 || (size_t)nret >= sizeof(attach_socket)) { ++ INFO("Failed to get full attach socket path"); ++ ret = -1; ++ goto out; ++ } ++ + p.exit_fifo = (char *)params->exit_fifo; + p.open_tty = params->tty; + p.open_stdin = params->open_stdin; +@@ -1042,6 +1071,7 @@ int rt_isula_create(const char *id, const char *runtime, const rt_create_params_ + p.isulad_stderr = (char *)params->stderr; + p.runtime_args = (char **)runtime_args; + p.runtime_args_len = runtime_args_len; ++ p.attach_socket = attach_socket; + copy_process(&p, config->process); + copy_annotations(&p, config->annotations); + +@@ -1224,7 +1254,7 @@ static bool fg_exec(const rt_exec_params_t *params) + return false; + } + +-static char *try_generate_exec_id() ++static char *try_generate_random_id() + { + char *id = NULL; + +@@ -1324,7 +1354,7 @@ int rt_isula_exec(const char *id, const char *runtime, const rt_exec_params_t *p + if (params->suffix != NULL) { + exec_id = util_strdup_s(params->suffix); + } else { +- exec_id = try_generate_exec_id(); ++ exec_id = try_generate_random_id(); + } + if (exec_id == NULL) { + ERROR("Out of memory or generate exec id failed"); +@@ -1423,13 +1453,133 @@ out: + return ret; + } + +-int rt_isula_attach(const char *id, const char *runtime, const rt_attach_params_t *params) ++static int get_container_attach_statuscode(const char *workdir, int attach_shim_fd) + { +- ERROR("isula attach not support on isulad-shim"); +- isulad_set_error_message("isula attach not support on isulad-shim"); ++ int status_code = 0; ++ int ret = -1; ++ struct timespec beg = { 0 }; ++ struct timespec end = { 0 }; ++ ++ if (clock_gettime(CLOCK_MONOTONIC, &beg) != 0) { ++ ERROR("Failed get time"); ++ return -1; ++ } ++ ++ while (true) { ++ if (clock_gettime(CLOCK_MONOTONIC, &end) != 0) { ++ ERROR("Failed get time"); ++ return -1; ++ } ++ if (end.tv_sec - beg.tv_sec > ATTACH_WAIT_TIME) { ++ ERROR("Wait container attach exitcode timeout"); ++ return -1; ++ } ++ ret = util_read_nointr(attach_shim_fd, &status_code, sizeof(int)); ++ if (ret <= 0) { ++ if (shim_alive(workdir)) { ++ // wait 100 millisecond to read exit code ++ util_usleep_nointerupt(100000); ++ continue; ++ } ++ ERROR("Failed read pid from dead shim %s", workdir); ++ return -1; ++ } ++ return status_code; /* success */ ++ } + return -1; + } + ++static int get_attach_socketfd(const char *attach_socket, int *socket_fd) ++{ ++ struct sockaddr_un addr = { 0 }; ++ __isula_auto_close int tmp_socket = -1; ++ ++ if (strlen(attach_socket) >= sizeof(addr.sun_path)) { ++ SYSERROR("Invalid attach socket path: %s", attach_socket); ++ return -1; ++ } ++ ++ tmp_socket = socket(AF_UNIX, SOCK_STREAM, 0); ++ if (tmp_socket < 0) { ++ SYSERROR("Failed to create attach socket"); ++ return -1; ++ } ++ ++ if (isula_set_non_block(tmp_socket) < 0) { ++ SYSERROR("Failed to set socket non block"); ++ return -1; ++ } ++ ++ (void)memset(&addr, 0, sizeof(addr)); ++ addr.sun_family = AF_UNIX; ++ (void)strcpy(addr.sun_path, attach_socket); ++ ++ if (connect(tmp_socket, (void *)&addr, sizeof(addr)) < 0) { ++ SYSERROR("Failed to connect attach socket: %s", attach_socket); ++ return -1; ++ } ++ *socket_fd = isula_transfer_fd(tmp_socket); ++ return 0; ++} ++ ++int rt_isula_attach(const char *id, const char *runtime, const rt_attach_params_t *params) ++{ ++ int ret = 0; ++ int len = 0; ++ int status_code = 0; ++ __isula_auto_close int socket_fd = -1; ++ char buf[BUFSIZ] = { 0 }; ++ char workdir[PATH_MAX] = { 0 }; ++ char attach_socket[PATH_MAX] = { 0 }; ++ ++ if (id == NULL || runtime == NULL || params == NULL) { ++ ERROR("Null argument"); ++ return -1; ++ } ++ ++ ret = snprintf(workdir, sizeof(workdir), "%s/%s", params->state, id); ++ if (ret < 0 || (size_t)ret >= sizeof(workdir)) { ++ ERROR("Failed join exec full path"); ++ return -1; ++ } ++ ++ // the communication format between isulad and isulad-shim attach is: ++ // stdin-path stdout-path stderr-path ++ len = snprintf(buf, sizeof(buf), "%s %s %s", params->stdin, params->stdout, params->stderr); ++ if (len < 0 || (size_t)len >= sizeof(buf)) { ++ ERROR("Failed to snprintf string"); ++ return -1; ++ } ++ ++ ret = snprintf(attach_socket, sizeof(attach_socket), "%s/%s", workdir, ATTACH_SOCKET); ++ if (ret < 0 || (size_t)ret >= sizeof(attach_socket)) { ++ ERROR("Failed to get full attach socket path"); ++ return -1; ++ } ++ ++ ret = get_attach_socketfd(attach_socket, &socket_fd); ++ if (ret < 0) { ++ ERROR("Failed to get attach socketfd"); ++ return -1; ++ } ++ ++ DEBUG("write %s to attach fd", buf); ++ ++ ret = isula_file_write_nointr(socket_fd, buf, len); ++ if (ret < 0) { ++ SYSERROR("Failed to write attach isulad fd"); ++ return -1; ++ } ++ ++ status_code = get_container_attach_statuscode(workdir, socket_fd); ++ if (status_code < 0) { ++ show_shim_attach_errlog(workdir); ++ return -1; ++ } ++ ++ return 0; ++} ++ + static int to_engine_resources_unified(const host_config *hostconfig, shim_client_cgroup_resources *cr) + { + int i; +@@ -1673,7 +1823,7 @@ static int parse_ps_data(char *stdout_msg, rt_listpids_out_t *out) + } + + static int runtime_call_ps(const char *workdir, const char *runtime, const char *id, +- rt_listpids_out_t *out) ++ rt_listpids_out_t *out) + { + __isula_auto_free char *stdout_msg = NULL; + __isula_auto_free char *stderr_msg = NULL; +@@ -1681,7 +1831,7 @@ static int runtime_call_ps(const char *workdir, const char *runtime, const char + int ret = 0; + int nret = 0; + char *params[PARAM_NUM] = { 0 }; +- const char *opts[2] = { "--format" , "json" }; ++ const char *opts[2] = { "--format", "json" }; + char root_path[PATH_MAX] = { 0 }; + + nret = snprintf(root_path, PATH_MAX, "%s/%s", workdir, runtime); +diff --git a/src/utils/cutils/error.h b/src/utils/cutils/error.h +index 088ed261..75eae760 100644 +--- a/src/utils/cutils/error.h ++++ b/src/utils/cutils/error.h +@@ -44,8 +44,10 @@ extern "C" { + /* err in runtime module */ \ + XX(ERR_RUNTIME, DEF_ERR_RUNTIME_STR) \ + \ ++ /* info for detach */ \ ++ XX(INFO_DETACH, "Attach detach") \ + /* err max */ \ +- XX(ERR_UNKNOWN, "Unknown error") ++ XX(ERR_UNKNOWN, "Unknown error") + + #define ISULAD_ERRNO_GEN(n, s) ISULAD_##n, + typedef enum { ISULAD_ERRNO_MAP(ISULAD_ERRNO_GEN) } isulad_errno_t; +-- +2.42.0 + diff --git a/0012-add-runc-attach-implement-unit-test-and-ci-test.patch b/0012-add-runc-attach-implement-unit-test-and-ci-test.patch new file mode 100644 index 0000000..401d89b --- /dev/null +++ b/0012-add-runc-attach-implement-unit-test-and-ci-test.patch @@ -0,0 +1,242 @@ +From d37c0c7ded0e107167a98dc1eda2000142d274f0 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Tue, 7 Nov 2023 16:39:50 +0800 +Subject: [PATCH 12/14] add runc attach implement unit test and ci test + +Signed-off-by: zhongtao +--- + CI/test_cases/container_cases/attach.sh | 153 ++++++++++++++++++++ + CI/test_cases/container_cases/cri_stream.sh | 6 +- + test/cmd/isulad-shim/common/common_ut.cc | 42 ++++++ + 3 files changed, 197 insertions(+), 4 deletions(-) + create mode 100755 CI/test_cases/container_cases/attach.sh + +diff --git a/CI/test_cases/container_cases/attach.sh b/CI/test_cases/container_cases/attach.sh +new file mode 100755 +index 00000000..0d362757 +--- /dev/null ++++ b/CI/test_cases/container_cases/attach.sh +@@ -0,0 +1,153 @@ ++#!/bin/bash ++# ++# attributes: isula attach test ++# concurrent: NA ++# spend time: 5 ++ ++####################################################################### ++##- 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. ++##- @Description:CI ++##- @Author: zhongtao ++##- @Create: 2023-11-06 ++####################################################################### ++ ++declare -r curr_path=$(dirname $(readlink -f "$0")) ++source ../helpers.sh ++ ++# $1 : retry limit ++# $2 : retry_interval ++# $3 : retry function ++function do_retry() ++{ ++ for i in $(seq 1 "$1"); do ++ $3 $4 $5 ++ if [ $? -ne 0 ]; then ++ return 0 ++ fi ++ sleep $2 ++ done ++ return 1 ++} ++ ++function get_ioCopy() ++{ ++ ps -T -p $(cat /var/run/isulad.pid) | grep IoCopy ++ return $? ++} ++ ++function inspect_container_status() ++{ ++ [[ $(isula inspect -f '{{.State.Status}}' ${1}) != "${2}" ]] ++ return $? ++} ++ ++function set_up() ++{ ++ local ret=0 ++ local runtime=$1 ++ ++ isula run -tid --name test --runtime $runtime busybox sh ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to run container with image: ${image}" && ((ret++)) ++ ++ msg_info "${test} finished with return ${ret}..." ++ return ${ret} ++} ++ ++function test_attach_fun() ++{ ++ local ret=0 ++ local retry_limit=20 ++ local retry_interval=1 ++ container_name="test" ++ local test="test_attach_fun => (${FUNCNAME[@]})" ++ ++ msg_info "${test} starting..." ++ ++ expect <<-END ++spawn isula attach test ++send \n ++expect "*" ++sleep 1 ++send "ls \r" ++expect "*" ++send "exit \r" ++expect "*" ++sleep 2 ++expect eof ++END ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to attach container test" && ((ret++)) ++ ++ count=$(isula logs test | grep ls | wc -l) ++ [[ $count -ne 1 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to do attach" && ((ret++)) ++ ++ do_retry ${retry_limit} ${retry_interval} inspect_container_status ${container_name} exited ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - incorrent container status: not Exited" && ((ret++)) ++ ++ (isula attach test > /tmp/test_attach1.log 2>&1) & ++ sleep 2 ++ cat /tmp/test_attach1.log | grep "You cannot attach to a stopped container, start it first" ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to do attach, except fail" && ((ret++)) ++ ++ rm -rf /tmp/test_attach1.log ++ ++ do_retry ${retry_limit} ${retry_interval} get_ioCopy ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - residual IO copy thread in CRI exec operation" && ((ret++)) ++ ++ msg_info "${test} finished with return ${ret}..." ++ return ${ret} ++} ++ ++function tear_down() ++{ ++ local ret=0 ++ ++ isula rm -f test ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to rm container: test" && ((ret++)) ++ ++ return ${ret} ++} ++ ++function do_test_t() ++{ ++ local ret=0 ++ local runtime=$1 ++ local test="basic attach test => (${runtime})" ++ msg_info "${test} starting..." ++ ++ set_up $runtime || ((ret++)) ++ ++ test_attach_fun || ((ret++)) ++ ++ tear_down || ((ret++)) ++ ++ msg_info "${test} finished with return ${ret}..." ++ ++ return $ret ++} ++ ++ret=0 ++ ++isula pull busybox ++[[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to pull image: ${image}" && return ${FAILURE} ++ ++isula images | grep busybox ++[[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - missing list image: ${image}" && ((ret++)) ++ ++for element in ${RUNTIME_LIST[@]}; ++do ++ do_test_t $element ++ if [ $? -ne 0 ];then ++ let "ret=$ret + 1" ++ fi ++done ++ ++show_result $ret "basic attach" ++ +diff --git a/CI/test_cases/container_cases/cri_stream.sh b/CI/test_cases/container_cases/cri_stream.sh +index 2360e240..43ed3891 100755 +--- a/CI/test_cases/container_cases/cri_stream.sh ++++ b/CI/test_cases/container_cases/cri_stream.sh +@@ -187,10 +187,8 @@ function do_test_t() + test_cri_exec_fun || ((ret++)) + test_cri_exec_abn || ((ret++)) + +- # runc attach not support +- if [ $runtime == "lcr" ]; then +- test_cri_attach || ((ret++)) +- fi ++ test_cri_attach || ((ret++)) ++ + tear_down || ((ret++)) + + msg_info "${test} finished with return ${ret}..." +diff --git a/test/cmd/isulad-shim/common/common_ut.cc b/test/cmd/isulad-shim/common/common_ut.cc +index 63395232..fb60f628 100644 +--- a/test/cmd/isulad-shim/common/common_ut.cc ++++ b/test/cmd/isulad-shim/common/common_ut.cc +@@ -87,3 +87,45 @@ TEST_F(CommonUnitTest, test_combined_output) + params[0] = non_cmd.c_str(); + EXPECT_EQ(cmd_combined_output(non_cmd.c_str(), params, output, &output_len), -1); + } ++ ++TEST_F(CommonUnitTest, test_get_attach_fifo_item) ++{ ++ struct isula_linked_list *attach_fifos = NULL; ++ attach_fifos = (struct isula_linked_list *)isula_common_calloc_s(sizeof(struct isula_linked_list)); ++ ASSERT_TRUE(attach_fifos != nullptr); ++ ++ isula_linked_list_init(attach_fifos); ++ ++ EXPECT_EQ(get_attach_fifo_item(4, attach_fifos), nullptr); ++ EXPECT_EQ(get_attach_fifo_item(-1, attach_fifos), nullptr); ++ EXPECT_EQ(get_attach_fifo_item(4, NULL), nullptr); ++ ++ struct shim_fifos_fd fifos1 = { ++ .in_fd = 1, ++ .out_fd = 2, ++ .err_fd = 3, ++ }; ++ struct shim_fifos_fd fifos2 = { ++ .in_fd = 4, ++ .out_fd = 5, ++ .err_fd = 6, ++ }; ++ struct isula_linked_list *node1 = NULL; ++ struct isula_linked_list *node2 = NULL; ++ node1 = (struct isula_linked_list *)isula_common_calloc_s(sizeof(struct isula_linked_list)); ++ ASSERT_TRUE(node1 != nullptr); ++ node1->elem = &fifos1; ++ isula_linked_list_add(attach_fifos, node1); ++ ++ node2 = (struct isula_linked_list *)isula_common_calloc_s(sizeof(struct isula_linked_list)); ++ ASSERT_TRUE(node2 != nullptr); ++ node2->elem = &fifos2; ++ isula_linked_list_add(attach_fifos, node2); ++ ++ EXPECT_EQ(get_attach_fifo_item(1, attach_fifos), node1); ++ EXPECT_EQ(get_attach_fifo_item(4, attach_fifos), node2); ++ ++ free(node1); ++ free(node2); ++ free(attach_fifos); ++} +-- +2.42.0 + diff --git a/0013-support-gcov-of-CI.patch b/0013-support-gcov-of-CI.patch new file mode 100644 index 0000000..14c4148 --- /dev/null +++ b/0013-support-gcov-of-CI.patch @@ -0,0 +1,26 @@ +From f4ea9145cea40cb97a86cd5eb91e1726cf48dd0d Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Tue, 14 Nov 2023 09:17:05 +0800 +Subject: [PATCH 13/14] support gcov of CI + +Signed-off-by: haozi007 +--- + CI/dockerfiles/Dockerfile-fedora | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/CI/dockerfiles/Dockerfile-fedora b/CI/dockerfiles/Dockerfile-fedora +index c30a3d0b..bef44377 100644 +--- a/CI/dockerfiles/Dockerfile-fedora ++++ b/CI/dockerfiles/Dockerfile-fedora +@@ -115,6 +115,8 @@ RUN echo "[source.crates-io]" >> ${HOME}/.cargo/config && \ + echo "[source.local-registry]" >> ${HOME}/.cargo/config && \ + echo "directory = \"vendor\"" >> ${HOME}/.cargo/config + ++RUN dnf install -y lcov && dnf clean all ++ + # install libevhtp + RUN export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH && \ + set -x && \ +-- +2.42.0 + diff --git a/0014-compatibility-for-manage-pods-which-created-by-old-i.patch b/0014-compatibility-for-manage-pods-which-created-by-old-i.patch new file mode 100644 index 0000000..ff36bcc --- /dev/null +++ b/0014-compatibility-for-manage-pods-which-created-by-old-i.patch @@ -0,0 +1,163 @@ +From 2bf2acb51aec12e734c970b02cd7802f088a2222 Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Tue, 14 Nov 2023 10:29:34 +0800 +Subject: [PATCH 14/14] compatibility for manage pods which created by old + iSulad + +Signed-off-by: haozi007 +--- + .../cri_pod_sandbox_manager_service.cc | 12 +++- + src/daemon/entry/cri/v1alpha/naming.cc | 72 ++++++++++++++++--- + src/daemon/entry/cri/v1alpha/naming.h | 2 +- + 3 files changed, 72 insertions(+), 14 deletions(-) + +diff --git a/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc b/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc +index 6e8f40b9..8533bb8c 100644 +--- a/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc ++++ b/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc +@@ -1153,7 +1153,11 @@ void PodSandboxManagerService::PodSandboxStatusToGRPC(const container_inspect *i + + CRIHelpers::ExtractLabels(inspect->config->labels, *podStatus->mutable_labels()); + CRIHelpers::ExtractAnnotations(inspect->config->annotations, *podStatus->mutable_annotations()); +- CRINaming::ParseSandboxName(podStatus->annotations(), *podStatus->mutable_metadata(), error); ++ std::string name; ++ if (inspect->name != nullptr) { ++ name = std::string(inspect->name); ++ } ++ CRINaming::ParseSandboxName(name, podStatus->annotations(), *podStatus->mutable_metadata(), error); + if (error.NotEmpty()) { + return; + } +@@ -1266,7 +1270,11 @@ void PodSandboxManagerService::ListPodSandboxToGRPC(container_list_response *res + + CRIHelpers::ExtractAnnotations(response->containers[i]->annotations, *pod->mutable_annotations()); + +- CRINaming::ParseSandboxName(pod->annotations(), *pod->mutable_metadata(), error); ++ std::string name; ++ if (response->containers[i]->name != nullptr) { ++ name = std::string(response->containers[i]->name); ++ } ++ CRINaming::ParseSandboxName(name, pod->annotations(), *pod->mutable_metadata(), error); + + if (filterOutReadySandboxes && pod->state() == runtime::v1alpha2::SANDBOX_READY) { + continue; +diff --git a/src/daemon/entry/cri/v1alpha/naming.cc b/src/daemon/entry/cri/v1alpha/naming.cc +index abb6e57d..de47a97d 100644 +--- a/src/daemon/entry/cri/v1alpha/naming.cc ++++ b/src/daemon/entry/cri/v1alpha/naming.cc +@@ -26,6 +26,38 @@ + #include "utils.h" + + namespace CRINaming { ++// default sandbox name create by MakeSandboxName(); ++// format is 'k8s_containername_metadataname_namespace_uid_attempt' ++static int parseName(const std::string &name, std::vector &items, unsigned int &attempt, Errors &err) ++{ ++ std::istringstream f(name); ++ std::string part; ++ ++ while (getline(f, part, CRI::Constants::nameDelimiterChar)) { ++ items.push_back(part); ++ } ++ ++ // format: k8s_containername_metadataname_namespace_uid_attempt ++ // so split name by '_', length of result array must be 6 ++ if (items.size() != 6) { ++ err.Errorf("failed to parse the sandbox name: %s", name.c_str()); ++ return -1; ++ } ++ ++ if (items[0] != CRI::Constants::kubePrefix) { ++ err.Errorf("container is not managed by kubernetes: %s", name.c_str()); ++ return -1; ++ } ++ ++ // last item index is 5, and must be attempt ++ if (util_safe_uint(items[5].c_str(), &attempt)) { ++ err.Errorf("failed to parse the sandbox name %s: %s", name.c_str(), strerror(errno)); ++ return -1; ++ } ++ ++ return 0; ++} ++ + std::string MakeSandboxName(const runtime::v1alpha2::PodSandboxMetadata &metadata) + { + std::string sname; +@@ -44,9 +76,12 @@ std::string MakeSandboxName(const runtime::v1alpha2::PodSandboxMetadata &metadat + return sname; + } + +-void ParseSandboxName(const google::protobuf::Map &annotations, ++void ParseSandboxName(const std::string &name, const google::protobuf::Map &annotations, + runtime::v1alpha2::PodSandboxMetadata &metadata, Errors &err) + { ++ // need check uid and attemp 2 items ++ int needSetUidAndAttemp = 2; ++ + if (annotations.count(CRIHelpers::Constants::SANDBOX_NAME_ANNOTATION_KEY) == 0) { + err.Errorf("annotation don't contains the sandbox name, failed to parse it"); + return; +@@ -57,21 +92,36 @@ void ParseSandboxName(const google::protobuf::Map &ann + return; + } + +- if (annotations.count(CRIHelpers::Constants::SANDBOX_UID_ANNOTATION_KEY) == 0) { +- err.Errorf("annotation don't contains the sandbox uid, failed to parse it"); +- return; ++ metadata.set_name(annotations.at(CRIHelpers::Constants::SANDBOX_NAME_ANNOTATION_KEY)); ++ metadata.set_namespace_(annotations.at(CRIHelpers::Constants::SANDBOX_NAMESPACE_ANNOTATION_KEY)); ++ ++ if (annotations.count(CRIHelpers::Constants::SANDBOX_UID_ANNOTATION_KEY) != 0) { ++ metadata.set_uid(annotations.at(CRIHelpers::Constants::SANDBOX_UID_ANNOTATION_KEY)); ++ needSetUidAndAttemp--; ++ } ++ ++ if (annotations.count(CRIHelpers::Constants::SANDBOX_ATTEMPT_ANNOTATION_KEY) != 0) { ++ auto sandboxAttempt = annotations.at(CRIHelpers::Constants::SANDBOX_ATTEMPT_ANNOTATION_KEY); ++ metadata.set_attempt(static_cast(std::stoul(sandboxAttempt))); ++ needSetUidAndAttemp--; + } + +- if (annotations.count(CRIHelpers::Constants::SANDBOX_ATTEMPT_ANNOTATION_KEY) == 0) { +- err.Errorf("annotation don't contains the sandbox attempt, failed to parse it"); ++ if (needSetUidAndAttemp == 0) { + return; + } + +- metadata.set_name(annotations.at(CRIHelpers::Constants::SANDBOX_NAME_ANNOTATION_KEY)); +- metadata.set_namespace_(annotations.at(CRIHelpers::Constants::SANDBOX_NAMESPACE_ANNOTATION_KEY)); +- metadata.set_uid(annotations.at(CRIHelpers::Constants::SANDBOX_UID_ANNOTATION_KEY)); +- auto sandboxAttempt = annotations.at(CRIHelpers::Constants::SANDBOX_ATTEMPT_ANNOTATION_KEY); +- metadata.set_attempt(static_cast(std::stoul(sandboxAttempt))); ++ // get uid and attempt from name, ++ // compatibility to new iSulad manage pods created by old version iSulad ++ // maybe should remove in next version of iSulad ++ std::vector items; ++ unsigned int attempt; ++ ++ if (parseName(name, items, attempt, err) != 0) { ++ return; ++ } ++ // index 4 in split array, must be uid ++ metadata.set_uid(items[4]); ++ metadata.set_attempt(static_cast(attempt)); + } + + std::string MakeContainerName(const runtime::v1alpha2::PodSandboxConfig &s, const runtime::v1alpha2::ContainerConfig &c) +diff --git a/src/daemon/entry/cri/v1alpha/naming.h b/src/daemon/entry/cri/v1alpha/naming.h +index 7eab41d3..f2d51a98 100644 +--- a/src/daemon/entry/cri/v1alpha/naming.h ++++ b/src/daemon/entry/cri/v1alpha/naming.h +@@ -26,7 +26,7 @@ std::string MakeSandboxName(const runtime::v1alpha2::PodSandboxMetadata &metadat + std::string MakeContainerName(const runtime::v1alpha2::PodSandboxConfig &s, + const runtime::v1alpha2::ContainerConfig &c); + +-void ParseSandboxName(const google::protobuf::Map &annotations, ++void ParseSandboxName(const std::string &name, const google::protobuf::Map &annotations, + runtime::v1alpha2::PodSandboxMetadata &metadata, Errors &err); + + void ParseContainerName(const google::protobuf::Map &annotations, +-- +2.42.0 + diff --git a/0015-2250-Remove-PERFMON-BPF-CHECKPOINT_RESTORE.patch b/0015-2250-Remove-PERFMON-BPF-CHECKPOINT_RESTORE.patch new file mode 100644 index 0000000..20223a6 --- /dev/null +++ b/0015-2250-Remove-PERFMON-BPF-CHECKPOINT_RESTORE.patch @@ -0,0 +1,33 @@ +From ba0460408ab6118e1ecf3dda242af1d4b0980777 Mon Sep 17 00:00:00 2001 +From: xuxuepeng +Date: Tue, 14 Nov 2023 14:00:31 +0000 +Subject: [PATCH 15/16] !2250 Remove PERFMON, BPF, CHECKPOINT_RESTORE Merge + pull request !2250 from xuxuepeng/master + +--- + src/utils/cutils/utils_cap.c | 9 --------- + 1 file changed, 9 deletions(-) + +diff --git a/src/utils/cutils/utils_cap.c b/src/utils/cutils/utils_cap.c +index 6473df45..8c9cfafa 100644 +--- a/src/utils/cutils/utils_cap.c ++++ b/src/utils/cutils/utils_cap.c +@@ -74,15 +74,6 @@ const char *g_all_caps[] = { + #ifdef CAP_AUDIT_READ + "CAP_AUDIT_READ", + #endif +-#ifdef CAP_PERFMON +- "CAP_PERFMON", +-#endif +-#ifdef CAP_BPF +- "CAP_BPF", +-#endif +-#ifdef CAP_CHECKPOINT_RESTORE +- "CAP_CHECKPOINT_RESTORE", +-#endif + }; + + static inline size_t util_get_all_caps_len() +-- +2.42.0 + diff --git a/0016-improve-event-logs.patch b/0016-improve-event-logs.patch new file mode 100644 index 0000000..afc4d5e --- /dev/null +++ b/0016-improve-event-logs.patch @@ -0,0 +1,202 @@ +From d611f18abac0f4077c9bf85f76162719cc5e55eb Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Tue, 14 Nov 2023 15:12:39 +0800 +Subject: [PATCH 16/64] improve event logs + +Signed-off-by: haozi007 +--- + .../grpc/cri/v1/cri_v1_runtime_runtime_service.cc | 13 ++++++++----- + .../grpc/cri/v1alpha/cri_runtime_runtime_service.cc | 10 +++++++--- + src/daemon/entry/cri/cni_network_plugin.cc | 6 +++--- + .../cri/v1alpha/cri_pod_sandbox_manager_service.cc | 3 ++- + src/daemon/executor/volume_cb/volume_cb.c | 4 ++-- + src/daemon/modules/network/native/adaptor_native.c | 8 ++++---- + 6 files changed, 26 insertions(+), 18 deletions(-) + +diff --git a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc +index b8d5746c..1db79307 100644 +--- a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc ++++ b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc +@@ -75,7 +75,7 @@ grpc::Status RuntimeV1RuntimeServiceImpl::CreateContainer(grpc::ServerContext *c + return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Invalid input arguments"); + } + +- EVENT("Event: {Object: CRI, Type: Creating Container}"); ++ EVENT("Event: {Object: CRI, Type: Creating Container for sandbox: %s}", request->pod_sandbox_id().c_str()); + + std::string responseID = + m_rService->CreateContainer(request->pod_sandbox_id(), request->config(), request->sandbox_config(), error); +@@ -316,17 +316,20 @@ grpc::Status RuntimeV1RuntimeServiceImpl::RunPodSandbox(grpc::ServerContext *con + ERROR("Invalid input arguments"); + return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Invalid input arguments"); + } +- +- EVENT("Event: {Object: CRI, Type: Running Pod}"); ++ if (request->has_config() && request->config().has_metadata()) { ++ EVENT("Event: {Object: CRI, Type: Running Pod: %s}", request->config().metadata().name().c_str()); ++ } else { ++ EVENT("Event: {Object: CRI, Type: Running Pod}"); ++ } + + std::string responseID = m_rService->RunPodSandbox(request->config(), request->runtime_handler(), error); + if (!error.Empty() || responseID.empty()) { +- ERROR("Object: CRI, Type: Failed to run pod:%s", error.GetMessage().c_str()); ++ ERROR("Object: CRI, Type: Failed to run pod: %s", error.GetMessage().c_str()); + return grpc::Status(grpc::StatusCode::UNKNOWN, error.GetMessage()); + } + reply->set_pod_sandbox_id(responseID); + +- EVENT("Event: {Object: CRI, Type: Run Pod success}"); ++ EVENT("Event: {Object: CRI, Type: Run Pod: %s success}", responseID.c_str()); + + return grpc::Status::OK; + } +diff --git a/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.cc b/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.cc +index ec3f01cd..a56b167c 100644 +--- a/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.cc ++++ b/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.cc +@@ -73,7 +73,7 @@ grpc::Status RuntimeRuntimeServiceImpl::CreateContainer(grpc::ServerContext *con + return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Invalid input arguments"); + } + +- EVENT("Event: {Object: CRI, Type: Creating Container}"); ++ EVENT("Event: {Object: CRI, Type: Creating Container for sandbox: %s}", request->pod_sandbox_id().c_str()); + + std::string responseID = + m_rService->CreateContainer(request->pod_sandbox_id(), request->config(), request->sandbox_config(), error); +@@ -315,7 +315,11 @@ grpc::Status RuntimeRuntimeServiceImpl::RunPodSandbox(grpc::ServerContext *conte + return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT, "Invalid input arguments"); + } + +- EVENT("Event: {Object: CRI, Type: Running Pod}"); ++ if (request->has_config() && request->config().has_metadata()) { ++ EVENT("Event: {Object: CRI, Type: Running Pod: %s}", request->config().metadata().name().c_str()); ++ } else { ++ EVENT("Event: {Object: CRI, Type: Running Pod}"); ++ } + + std::string responseID = m_rService->RunPodSandbox(request->config(), request->runtime_handler(), error); + if (!error.Empty() || responseID.empty()) { +@@ -324,7 +328,7 @@ grpc::Status RuntimeRuntimeServiceImpl::RunPodSandbox(grpc::ServerContext *conte + } + reply->set_pod_sandbox_id(responseID); + +- EVENT("Event: {Object: CRI, Type: Run Pod success}"); ++ EVENT("Event: {Object: CRI, Type: Run Pod: %s success}", responseID.c_str()); + + return grpc::Status::OK; + } +diff --git a/src/daemon/entry/cri/cni_network_plugin.cc b/src/daemon/entry/cri/cni_network_plugin.cc +index 656fceda..377796ee 100644 +--- a/src/daemon/entry/cri/cni_network_plugin.cc ++++ b/src/daemon/entry/cri/cni_network_plugin.cc +@@ -612,12 +612,12 @@ void CniNetworkPlugin::SetUpPod(const std::string &ns, const std::string &name, + if (g_isulad_errmsg != nullptr) { + err.SetError(g_isulad_errmsg); + } else { +- err.Errorf("setup cni for container: %s failed", id.c_str()); ++ err.Errorf("setup cni for sandbox: %s failed", id.c_str()); + } + // rollback all network plane + // if mutl-networks, one network plane failed, cause to left network can not be delete. + if (network_module_detach(config, NETWOKR_API_TYPE_CRI) != 0) { +- WARN("rollback all network for: %s failed", id.c_str()); ++ WARN("rollback all network for sandbox: %s failed", id.c_str()); + } + } + +@@ -671,7 +671,7 @@ void CniNetworkPlugin::TearDownPod(const std::string &ns, const std::string &nam + } + + if (network_module_detach(config, NETWOKR_API_TYPE_CRI) != 0) { +- err.Errorf("teardown cni for container: %s failed", id.c_str()); ++ err.Errorf("teardown cni for sandbox: %s failed", id.c_str()); + } + + UnlockNetworkMap(err); +diff --git a/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc b/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc +index 8533bb8c..8eff22ac 100644 +--- a/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc ++++ b/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc +@@ -618,6 +618,7 @@ auto PodSandboxManagerService::RunPodSandbox(const runtime::v1alpha2::PodSandbox + // Step 2: Create the sandbox container. + response_id = CreateSandboxContainer(config, image, jsonCheckpoint, runtimeHandler, error); + if (error.NotEmpty()) { ++ ERROR("Create sandbox failed: %s", error.GetCMessage()); + goto cleanup; + } + +@@ -672,7 +673,7 @@ auto PodSandboxManagerService::RunPodSandbox(const runtime::v1alpha2::PodSandbox + UpdatePodSandboxNetworkSettings(response_id, network_setting_json, tmpErr); + // If saving network settings failed, ignore error + if (tmpErr.NotEmpty()) { +- WARN("%s", tmpErr.GetCMessage()); ++ WARN("Update sandbox network setting err: %s", tmpErr.GetCMessage()); + } + } + goto cleanup; +diff --git a/src/daemon/executor/volume_cb/volume_cb.c b/src/daemon/executor/volume_cb/volume_cb.c +index 2148922e..ff5973b8 100644 +--- a/src/daemon/executor/volume_cb/volume_cb.c ++++ b/src/daemon/executor/volume_cb/volume_cb.c +@@ -52,7 +52,7 @@ static int volume_list_cb(const volume_list_volume_request *request, volume_list + goto err_out; + } + +- EVENT("Volume Event: {Object: list volumes, Type: listing}"); ++ INFO("Volume Event: {Object: list volumes, Type: listing}"); + + list = volume_list(); + if (list == NULL) { +@@ -85,7 +85,7 @@ static int volume_list_cb(const volume_list_volume_request *request, volume_list + } + + out: +- EVENT("Volume Event: {Object: list volumes, Type: listed"); ++ INFO("Volume Event: {Object: list volumes, Type: listed"); + + err_out: + if (*response != NULL) { +diff --git a/src/daemon/modules/network/native/adaptor_native.c b/src/daemon/modules/network/native/adaptor_native.c +index 45288d7e..baaecc32 100644 +--- a/src/daemon/modules/network/native/adaptor_native.c ++++ b/src/daemon/modules/network/native/adaptor_native.c +@@ -1510,7 +1510,7 @@ int native_config_inspect(const char *name, char **network_json) + return -1; + } + +- EVENT("Event: {Object: network, Type: inspecting, Target: %s}", name); ++ INFO("Event: {Object: network, Type: inspecting, Target: %s}", name); + + if (!native_store_lock(SHARED)) { + return -1; +@@ -1538,7 +1538,7 @@ int native_config_inspect(const char *name, char **network_json) + + // TODO: inspect the linked containers ip info + +- EVENT("Event: {Object: network, Type: inspected, Target: %s}", name); ++ INFO("Event: {Object: network, Type: inspected, Target: %s}", name); + goto out; + } + +@@ -1635,7 +1635,7 @@ int native_config_list(const struct filters_args *filters, network_network_info + return -1; + } + +- EVENT("Event: {Object: network, Type: listing}"); ++ INFO("Event: {Object: network, Type: listing}"); + + if (!native_store_lock(SHARED)) { + return -1; +@@ -1693,7 +1693,7 @@ int native_config_list(const struct filters_args *filters, network_network_info + *networks_len = nets_len; + nets_len = 0; + +- EVENT("Event: {Object: network, Type: listed}"); ++ INFO("Event: {Object: network, Type: listed}"); + + out: + map_itor_free(itor); +-- +2.42.0 + diff --git a/0017-2251-open-ENABLE_GRPC_REMOTE_CONNECT-in-CI.patch b/0017-2251-open-ENABLE_GRPC_REMOTE_CONNECT-in-CI.patch new file mode 100644 index 0000000..0002444 --- /dev/null +++ b/0017-2251-open-ENABLE_GRPC_REMOTE_CONNECT-in-CI.patch @@ -0,0 +1,57 @@ +From 48dc6f0adda72d7f4742afe1b8380370debfe4f4 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Wed, 15 Nov 2023 03:10:15 +0000 +Subject: [PATCH 17/64] !2251 open ENABLE_GRPC_REMOTE_CONNECT in CI * open + ENABLE_GRPC_REMOTE_CONNECT in CI + +--- + CI/make-and-install.sh | 4 ++-- + CI/only_build_isulad.sh | 2 +- + CI/pr-gateway.sh | 2 +- + 3 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/CI/make-and-install.sh b/CI/make-and-install.sh +index cdd0e432..c1d26ff1 100755 +--- a/CI/make-and-install.sh ++++ b/CI/make-and-install.sh +@@ -103,9 +103,9 @@ rm -rf build + mkdir build + cd build + if [[ ${enable_gcov} -ne 0 ]]; then +- cmake -DLIB_INSTALL_DIR=${builddir}/lib -DCMAKE_INSTALL_PREFIX=${builddir} -DCMAKE_INSTALL_SYSCONFDIR=${builddir}/etc -DCMAKE_BUILD_TYPE=Debug -DGCOV=ON -DENABLE_EMBEDDED=ON -DENABLE_COVERAGE=ON -DENABLE_CRI_API_V1=ON -DENABLE_UT=ON -DENABLE_METRICS=ON -DENABLE_REMOTE_LAYER_STORE=ON .. ++ cmake -DLIB_INSTALL_DIR=${builddir}/lib -DCMAKE_INSTALL_PREFIX=${builddir} -DCMAKE_INSTALL_SYSCONFDIR=${builddir}/etc -DCMAKE_BUILD_TYPE=Debug -DGCOV=ON -DENABLE_EMBEDDED=ON -DENABLE_COVERAGE=ON -DENABLE_CRI_API_V1=ON -DENABLE_UT=ON -DENABLE_METRICS=ON -DENABLE_REMOTE_LAYER_STORE=ON -DENABLE_GRPC_REMOTE_CONNECT=ON .. + else +- cmake -DLIB_INSTALL_DIR=${builddir}/lib -DCMAKE_INSTALL_PREFIX=${builddir} -DCMAKE_INSTALL_SYSCONFDIR=${builddir}/etc -DENABLE_EMBEDDED=ON -DENABLE_METRICS=ON -DENABLE_REMOTE_LAYER_STORE=ON -DENABLE_CRI_API_V1=ON .. ++ cmake -DLIB_INSTALL_DIR=${builddir}/lib -DCMAKE_INSTALL_PREFIX=${builddir} -DCMAKE_INSTALL_SYSCONFDIR=${builddir}/etc -DENABLE_EMBEDDED=ON -DENABLE_METRICS=ON -DENABLE_REMOTE_LAYER_STORE=ON -DENABLE_CRI_API_V1=ON -DENABLE_GRPC_REMOTE_CONNECT=ON .. + fi + make -j $(nproc) + make install +diff --git a/CI/only_build_isulad.sh b/CI/only_build_isulad.sh +index d2d3417d..c3dc39d6 100755 +--- a/CI/only_build_isulad.sh ++++ b/CI/only_build_isulad.sh +@@ -67,7 +67,7 @@ popd + git clone https://gitee.com/openeuler/iSulad.git + pushd iSulad + mkdir build && pushd build +-cmake -DENABLE_UT=ON ../ ++cmake -DENABLE_UT=ON -DENABLE_GRPC_REMOTE_CONNECT=ON ../ + make -j2 && make install + ctest -V + popd +diff --git a/CI/pr-gateway.sh b/CI/pr-gateway.sh +index 291fc4ae..08bcfc4f 100755 +--- a/CI/pr-gateway.sh ++++ b/CI/pr-gateway.sh +@@ -99,7 +99,7 @@ pushd iSulad + rm -rf build + mkdir build + pushd build +-cmake -DDEBUG=ON -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_UT=ON -DENABLE_CRI_API_V1=ON -DENABLE_REMOTE_LAYER_STORE=ON -DENABLE_SHIM_V2=OFF ../ || exit 1 ++cmake -DDEBUG=ON -DCMAKE_INSTALL_PREFIX=/usr -DENABLE_UT=ON -DENABLE_CRI_API_V1=ON -DENABLE_REMOTE_LAYER_STORE=ON -DENABLE_SHIM_V2=OFF -DENABLE_GRPC_REMOTE_CONNECT=ON ../ || exit 1 + make -j $(nproc) || exit 1 + ctest -V + popd +-- +2.42.0 + diff --git a/0018-Add-compatibility-between-iSulad-and-k8s.patch b/0018-Add-compatibility-between-iSulad-and-k8s.patch new file mode 100644 index 0000000..48d9f0c --- /dev/null +++ b/0018-Add-compatibility-between-iSulad-and-k8s.patch @@ -0,0 +1,57 @@ +From bec48dcd219885abd72cb9973a2e810e3f504269 Mon Sep 17 00:00:00 2001 +From: jikai +Date: Wed, 15 Nov 2023 10:51:01 +0800 +Subject: [PATCH 18/64] Add compatibility between iSulad and k8s + +Signed-off-by: jikai +--- + README.md | 13 ++++++++++++- + README_zh.md | 12 +++++++++++- + 2 files changed, 23 insertions(+), 2 deletions(-) + +diff --git a/README.md b/README.md +index 7e4b6de1..e7949dee 100644 +--- a/README.md ++++ b/README.md +@@ -233,4 +233,15 @@ The standard specification versions that `iSulad` is compatible with are as foll + + - Compatible with OCI 1.0.0. + - Compatible with CNI 0.3.0 and above. +-- Compatible with lcr 2.1.x and above. +\ No newline at end of file ++- Compatible with lcr 2.1.x and above. ++ ++## Kubernetes Support ++ ++`iSulad` supports Kubernetes version 1.13 and above. The following table shows the compatibility between `iSulad` and Kubernetes. ++It lists the minimum `iSulad` version required for some given Kubernetes versions. ++ ++iSulad Version | Kubernetes Version | CRI Version ++--- | --- | --- ++v2.0.0+ | v1.13-v1.18 | v1alpha2 ++v2.0.8+ | v1.19-v1.22 | v1alpha2 ++v2.1.4+ | v1.23-v1.26 | v1, v1alpha2 +diff --git a/README_zh.md b/README_zh.md +index 72942765..1c4dff4f 100755 +--- a/README_zh.md ++++ b/README_zh.md +@@ -229,4 +229,14 @@ $ sudo isula rm test + + - 兼容 1.0.0 版本的OCI + - 兼容 0.3.0 版本以上的CNI +-- 兼容 2.1.x 版本以上的lcr +\ No newline at end of file ++- 兼容 2.1.x 版本以上的lcr ++ ++## Kubernetes Support ++ ++`iSulad`提供对Kubernetes 1.13 版本以上的支持。以下表格显示了 `iSulad` 与 Kubernetes 之间的兼容性。它给出了指定Kubernetes版本下所需要的最低 `iSulad` 版本。 ++ ++iSulad 版本 | Kubernetes 版本 | CRI 版本 ++--- | --- | --- ++v2.0.0+ | v1.13-v1.18 | v1alpha2 ++v2.0.8+ | v1.19-v1.22 | v1alpha2 ++v2.1.4+ | v1.23-v1.26 | v1, v1alpha2 +-- +2.42.0 + diff --git a/0019-2254-lcr-container-with-a-damaged-config-file-will-r.patch b/0019-2254-lcr-container-with-a-damaged-config-file-will-r.patch new file mode 100644 index 0000000..c371d1a --- /dev/null +++ b/0019-2254-lcr-container-with-a-damaged-config-file-will-r.patch @@ -0,0 +1,384 @@ +From 21bca2bb054ed7a1b9b78e01965f8a6d9c3fd28d Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Mon, 20 Nov 2023 12:58:26 +0000 +Subject: [PATCH 19/64] !2254 lcr container with a damaged config file will + rebuild the config during restore * lcr container with a damaged config file + will rebuild the config during restore + +--- + src/common/constants.h | 2 + + src/daemon/modules/api/runtime_api.h | 7 ++ + .../modules/container/restore/restore.c | 28 ++++-- + .../modules/runtime/engines/lcr/lcr_rt_ops.c | 99 ++++++++++++++++++- + .../modules/runtime/engines/lcr/lcr_rt_ops.h | 1 + + .../modules/runtime/isula/isula_rt_ops.c | 6 ++ + .../modules/runtime/isula/isula_rt_ops.h | 1 + + src/daemon/modules/runtime/runtime.c | 24 +++++ + src/daemon/modules/runtime/shim/shim_rt_ops.c | 6 ++ + src/daemon/modules/runtime/shim/shim_rt_ops.h | 2 + + 10 files changed, 167 insertions(+), 9 deletions(-) + +diff --git a/src/common/constants.h b/src/common/constants.h +index caf9b793..5f12ae25 100644 +--- a/src/common/constants.h ++++ b/src/common/constants.h +@@ -86,6 +86,8 @@ extern "C" { + + #define LOG_MAX_RETRIES 10 + ++#define INVALID_CONFIG_ERR_CODE 2 ++ + #define MAX_MSG_BUFFER_SIZE (32 * 1024) + + #define DEFAULT_WEBSOCKET_SERVER_LISTENING_PORT 10350 +diff --git a/src/daemon/modules/api/runtime_api.h b/src/daemon/modules/api/runtime_api.h +index 3c2100f5..08558f42 100644 +--- a/src/daemon/modules/api/runtime_api.h ++++ b/src/daemon/modules/api/runtime_api.h +@@ -41,6 +41,7 @@ typedef enum { + struct runtime_container_status_info { + bool has_pid; + uint32_t pid; ++ int error_code; + Runtime_Container_Status status; + }; + +@@ -197,6 +198,10 @@ typedef struct _rt_exec_resize_params_t { + unsigned int width; + } rt_exec_resize_params_t; + ++typedef struct _rt_runtime_rebuild_config_params_t { ++ const char *rootpath; ++} rt_rebuild_config_params_t; ++ + struct rt_ops { + /* detect whether runtime is of this runtime type */ + bool (*detect)(const char *runtime); +@@ -233,6 +238,7 @@ struct rt_ops { + rt_listpids_out_t *out); + int (*rt_resize)(const char *name, const char *runtime, const rt_resize_params_t *params); + int (*rt_exec_resize)(const char *name, const char *runtime, const rt_exec_resize_params_t *params); ++ int (*rt_rebuild_config)(const char *name, const char *runtime, const rt_rebuild_config_params_t *params); + }; + + int runtime_create(const char *name, const char *runtime, const rt_create_params_t *params); +@@ -253,6 +259,7 @@ int runtime_attach(const char *name, const char *runtime, const rt_attach_params + int runtime_update(const char *name, const char *runtime, const rt_update_params_t *params); + + int runtime_listpids(const char *name, const char *runtime, const rt_listpids_params_t *params, rt_listpids_out_t *out); ++int runtime_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params); + void free_rt_listpids_out_t(rt_listpids_out_t *out); + int runtime_resize(const char *name, const char *runtime, const rt_resize_params_t *params); + int runtime_exec_resize(const char *name, const char *runtime, const rt_exec_resize_params_t *params); +diff --git a/src/daemon/modules/container/restore/restore.c b/src/daemon/modules/container/restore/restore.c +index c26cf561..f6218fe6 100644 +--- a/src/daemon/modules/container/restore/restore.c ++++ b/src/daemon/modules/container/restore/restore.c +@@ -16,15 +16,18 @@ + #include + #include + #include +-#include +-#include + #include + #include + #include + #include + ++#include ++#include ++#include ++#include ++ + #include "isulad_config.h" +-#include "isula_libutils/log.h" ++ + #include "container_api.h" + #include "supervisor.h" + #include "containers_gc.h" +@@ -276,9 +279,22 @@ static void restore_state(container_t *cont) + #endif + nret = runtime_status(id, runtime, ¶ms, &real_status); + if (nret != 0) { +- WARN("Failed to restore container %s, make real status to STOPPED. Due to can not load container with status %d", +- id, status); +- real_status.status = RUNTIME_CONTAINER_STATUS_STOPPED; ++ bool rebuild_config = (real_status.error_code == INVALID_CONFIG_ERR_CODE); ++ int tempret = -1; ++ // only the lcr container with a damaged config file will rebuild the config ++ if (rebuild_config) { ++ rt_rebuild_config_params_t rebuild_params = { 0 }; ++ rebuild_params.rootpath = cont->root_path; ++ nret = runtime_rebuild_config(id, runtime, &rebuild_params); ++ EVENT("Rebuild config for container: %s, result : %d", id, nret); ++ if (nret == 0) { ++ tempret = runtime_status(id, runtime, ¶ms, &real_status); ++ } ++ } ++ if (tempret != 0) { ++ WARN("Failed to restore container %s, make real status to STOPPED. Due to cannot load container with status %d", id, status); ++ real_status.status = RUNTIME_CONTAINER_STATUS_STOPPED; ++ } + } + + if (real_status.status == RUNTIME_CONTAINER_STATUS_STOPPED) { +diff --git a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c +index f61316d0..2f42909b 100644 +--- a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c ++++ b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c +@@ -16,15 +16,18 @@ + #include + #include + #include +-#include +-#include + #include + #include + #include + #include + ++#include ++#include ++#include ++#include ++#include ++ + #include "lcr_rt_ops.h" +-#include "isula_libutils/log.h" + #include "engine.h" + #include "error.h" + #include "isulad_config.h" +@@ -32,6 +35,8 @@ + #include "runtime_api.h" + #include "utils_file.h" + ++#define LCR_CONFIG_FILE "config" ++ + bool rt_lcr_detect(const char *runtime) + { + /* now we just support lcr engine */ +@@ -276,6 +281,17 @@ int rt_lcr_status(const char *name, const char *runtime, const rt_status_params_ + nret = engine_ops->engine_get_container_status_op(name, params->rootpath, status); + if (nret != 0) { + ret = -1; ++ const char *tmpmsg = NULL; ++ if (engine_ops->engine_get_errmsg_op != NULL) { ++ tmpmsg = engine_ops->engine_get_errmsg_op(); ++ } ++ if (tmpmsg != NULL && strstr(tmpmsg, "Failed to load config") != NULL) { ++ status->error_code = INVALID_CONFIG_ERR_CODE; ++ } ++ isulad_set_error_message("Runtime state container error: %s", ++ (tmpmsg != NULL && strcmp(tmpmsg, DEF_SUCCESS_STR)) != 0 ? tmpmsg : DEF_ERR_RUNTIME_STR); ++ ERROR("Runtime state container error: %s", ++ (tmpmsg != NULL && strcmp(tmpmsg, DEF_SUCCESS_STR)) != 0 ? tmpmsg : DEF_ERR_RUNTIME_STR); + goto out; + } + +@@ -756,3 +772,80 @@ int rt_lcr_kill(const char *id, const char *runtime, const rt_kill_params_t *par + + return 0; + } ++ ++int rt_lcr_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params) ++{ ++ int ret = -1; ++ int nret = 0; ++ char config_file[PATH_MAX] = { 0 }; ++ char bak_config_file[PATH_MAX] = { 0 }; ++ char oci_config_file[PATH_MAX] = { 0 }; ++ struct engine_operation *engine_ops = NULL; ++ oci_runtime_spec *oci_spec = NULL; ++ __isula_auto_free char *json_container = NULL; ++ __isula_auto_free parser_error err = NULL; ++ ++ engine_ops = engines_get_handler(runtime); ++ if (engine_ops == NULL || engine_ops->engine_create_op == NULL) { ++ ERROR("Failed to get engine rebuild config operations"); ++ return -1; ++ } ++ ++ nret = snprintf(config_file, PATH_MAX, "%s/%s/%s", params->rootpath, name, LCR_CONFIG_FILE); ++ if (nret < 0 || (size_t)nret >= PATH_MAX) { ++ ERROR("Failed to snprintf config file for container %s", name); ++ return -1; ++ } ++ ++ nret = snprintf(bak_config_file, PATH_MAX, "%s/%s/%s", params->rootpath, name, ".tmp_config_bak"); ++ if (nret < 0 || (size_t)nret >= PATH_MAX) { ++ ERROR("Failed to snprintf bak config file for container %s", name); ++ return -1; ++ } ++ ++ nret = snprintf(oci_config_file, sizeof(oci_config_file), "%s/%s/%s", params->rootpath, name, OCI_CONFIG_JSON); ++ if (nret < 0 || (size_t)nret >= sizeof(oci_config_file)) { ++ ERROR("Failed to snprintf for config json"); ++ return -1; ++ } ++ ++ oci_spec = oci_runtime_spec_parse_file(oci_config_file, NULL, &err); ++ if (oci_spec == NULL) { ++ ERROR("Failed to parse oci config file:%s", err); ++ return -1; ++ } ++ ++ // delete the bak config file to prevent the remnants of the previous bak file ++ if (util_fileself_exists(bak_config_file) && util_path_remove(bak_config_file) != 0) { ++ ERROR("Failed to remove bak_config_file for container: %s", name); ++ goto out; ++ } ++ ++ if (util_fileself_exists(config_file) && rename(config_file, bak_config_file) != 0) { ++ ERROR("Failed to backup old config for container: %s", name); ++ goto out; ++ } ++ ++ nret = engine_ops->engine_create_op(name, params->rootpath, (void *)oci_spec); ++ if (nret != 0) { ++ // delete the invalid config file to prevent rename failed ++ if (util_fileself_exists(config_file) && util_path_remove(config_file) != 0) { ++ WARN("Failed to remove bak_config_file for container %s", name); ++ } ++ if (util_fileself_exists(bak_config_file) && rename(bak_config_file, config_file) != 0) { ++ WARN("Failed to rename backup old config to config for container %s", name); ++ } ++ } ++ ++ ret = 0; ++ ++out: ++ if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { ++ engine_ops->engine_clear_errmsg_op(); ++ } ++ if (util_fileself_exists(bak_config_file) && util_path_remove(bak_config_file) != 0) { ++ WARN("Failed to remove bak_config_file for %s", name); ++ } ++ free_oci_runtime_spec(oci_spec); ++ return ret; ++} +diff --git a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.h b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.h +index 5b74ad6c..7403544d 100644 +--- a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.h ++++ b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.h +@@ -47,6 +47,7 @@ int rt_lcr_resources_stats(const char *name, const char *runtime, const rt_stats + int rt_lcr_resize(const char *id, const char *runtime, const rt_resize_params_t *params); + int rt_lcr_exec_resize(const char *id, const char *runtime, const rt_exec_resize_params_t *params); + int rt_lcr_kill(const char *id, const char *runtime, const rt_kill_params_t *params); ++int rt_lcr_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params); + #ifdef __cplusplus + } + #endif +diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c +index 1787170b..83214c1a 100644 +--- a/src/daemon/modules/runtime/isula/isula_rt_ops.c ++++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c +@@ -2013,3 +2013,9 @@ int rt_isula_kill(const char *id, const char *runtime, const rt_kill_params_t *p + + return 0; + } ++ ++// the config file of oci runtime is config.json. If it is damaged, it cannot be rebuilt. ++int rt_isula_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params) ++{ ++ return 0; ++} +\ No newline at end of file +diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.h b/src/daemon/modules/runtime/isula/isula_rt_ops.h +index 49b6cc0e..1e5e049a 100644 +--- a/src/daemon/modules/runtime/isula/isula_rt_ops.h ++++ b/src/daemon/modules/runtime/isula/isula_rt_ops.h +@@ -46,6 +46,7 @@ int rt_isula_resources_stats(const char *name, const char *runtime, const rt_sta + int rt_isula_resize(const char *id, const char *runtime, const rt_resize_params_t *params); + int rt_isula_exec_resize(const char *id, const char *runtime, const rt_exec_resize_params_t *params); + int rt_isula_kill(const char *id, const char *runtime, const rt_kill_params_t *params); ++int rt_isula_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params); + + #ifdef __cplusplus + } +diff --git a/src/daemon/modules/runtime/runtime.c b/src/daemon/modules/runtime/runtime.c +index cb383970..d9a332af 100644 +--- a/src/daemon/modules/runtime/runtime.c ++++ b/src/daemon/modules/runtime/runtime.c +@@ -45,6 +45,7 @@ static const struct rt_ops g_lcr_rt_ops = { + .rt_resize = rt_lcr_resize, + .rt_exec_resize = rt_lcr_exec_resize, + .rt_kill = rt_lcr_kill, ++ .rt_rebuild_config = rt_lcr_rebuild_config, + }; + + static const struct rt_ops g_isula_rt_ops = { +@@ -65,6 +66,7 @@ static const struct rt_ops g_isula_rt_ops = { + .rt_resize = rt_isula_resize, + .rt_exec_resize = rt_isula_exec_resize, + .rt_kill = rt_isula_kill, ++ .rt_rebuild_config = rt_isula_rebuild_config, + }; + + #ifdef ENABLE_SHIM_V2 +@@ -86,6 +88,7 @@ static const struct rt_ops g_shim_rt_ops = { + .rt_resize = rt_shim_resize, + .rt_exec_resize = rt_shim_exec_resize, + .rt_kill = rt_shim_kill, ++ .rt_rebuild_config = rt_shim_rebuild_config, + }; + #endif + +@@ -465,6 +468,27 @@ out: + return ret; + } + ++int runtime_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params) ++{ ++ int ret = 0; ++ const struct rt_ops *ops = NULL; ++ ++ if (name == NULL || runtime == NULL || params == NULL) { ++ ERROR("Invalid arguments for runtime rebuild config"); ++ return -1; ++ } ++ ++ ops = rt_ops_query(runtime); ++ if (ops == NULL) { ++ ERROR("Failed to get runtime ops"); ++ return -1; ++ } ++ ++ ret = ops->rt_rebuild_config(name, runtime, params); ++ ++ return ret; ++} ++ + int runtime_resize(const char *name, const char *runtime, const rt_resize_params_t *params) + { + int ret = 0; +diff --git a/src/daemon/modules/runtime/shim/shim_rt_ops.c b/src/daemon/modules/runtime/shim/shim_rt_ops.c +index 550b17f3..56fc43c2 100644 +--- a/src/daemon/modules/runtime/shim/shim_rt_ops.c ++++ b/src/daemon/modules/runtime/shim/shim_rt_ops.c +@@ -805,3 +805,9 @@ int rt_shim_kill(const char *id, const char *runtime, const rt_kill_params_t *pa + + return 0; + } ++ ++// the config file of oci runtime is config.json. If it is damaged, it cannot be rebuilt. ++int rt_shim_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params) ++{ ++ return 0; ++} +\ No newline at end of file +diff --git a/src/daemon/modules/runtime/shim/shim_rt_ops.h b/src/daemon/modules/runtime/shim/shim_rt_ops.h +index 03b7c018..2df34f4c 100644 +--- a/src/daemon/modules/runtime/shim/shim_rt_ops.h ++++ b/src/daemon/modules/runtime/shim/shim_rt_ops.h +@@ -62,6 +62,8 @@ int rt_shim_exec_resize(const char *id, const char *runtime, const rt_exec_resiz + + bool is_valid_v2_runtime(const char* name); + ++int rt_shim_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params); ++ + #ifdef __cplusplus + } + #endif +-- +2.42.0 + diff --git a/0020-2253-bugfix-for-runc-container-exec.patch b/0020-2253-bugfix-for-runc-container-exec.patch new file mode 100644 index 0000000..bf00f1e --- /dev/null +++ b/0020-2253-bugfix-for-runc-container-exec.patch @@ -0,0 +1,39 @@ +From 6b636051af158fac017998732d7d121b8ea71081 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Mon, 20 Nov 2023 12:59:09 +0000 +Subject: [PATCH 20/64] !2253 bugfix for runc container exec * bugfix for runc + container exec + +--- + src/daemon/modules/runtime/isula/isula_rt_ops.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c +index 83214c1a..e61d1f91 100644 +--- a/src/daemon/modules/runtime/isula/isula_rt_ops.c ++++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c +@@ -1386,17 +1386,16 @@ int rt_isula_exec(const char *id, const char *runtime, const rt_exec_params_t *p + } + + ret = shim_create(fg_exec(params), id, workdir, bundle, cmd, exit_code, timeout, &shim_exit_code); +- if (ret != 0) { +- ERROR("%s: failed create shim process for exec %s", id, exec_id); +- goto errlog_out; +- } +- + if (shim_exit_code == SHIM_EXIT_TIMEOUT) { + ret = -1; + isulad_set_error_message("Exec container error;exec timeout"); + ERROR("isulad-shim %d exit for execing timeout", pid); + goto errlog_out; + } ++ if (ret != 0) { ++ ERROR("%s: failed create shim process for exec %s", id, exec_id); ++ goto errlog_out; ++ } + + pid = get_container_process_pid(workdir); + if (pid < 0) { +-- +2.42.0 + diff --git a/0021-bugfix-of-update-restart-policy-for-auto-remove-cont.patch b/0021-bugfix-of-update-restart-policy-for-auto-remove-cont.patch new file mode 100644 index 0000000..6d0ba03 --- /dev/null +++ b/0021-bugfix-of-update-restart-policy-for-auto-remove-cont.patch @@ -0,0 +1,58 @@ +From ea51fa836464660fcca245e7e36a2b4cdf1e5997 Mon Sep 17 00:00:00 2001 +From: zhangxiaoyu +Date: Tue, 21 Nov 2023 10:23:26 +0800 +Subject: [PATCH 21/64] bugfix of update restart policy for auto remove + container + +Signed-off-by: zhangxiaoyu +--- + .../executor/container_cb/execution_extend.c | 18 +++++++++++------- + 1 file changed, 11 insertions(+), 7 deletions(-) + +diff --git a/src/daemon/executor/container_cb/execution_extend.c b/src/daemon/executor/container_cb/execution_extend.c +index 6759a4fc..de017b4e 100644 +--- a/src/daemon/executor/container_cb/execution_extend.c ++++ b/src/daemon/executor/container_cb/execution_extend.c +@@ -1113,15 +1113,14 @@ static int update_host_config_check(container_t *cont, host_config *hostconfig) + + ret = verify_host_config_settings(hostconfig, true); + if (ret != 0) { +- goto out; ++ return -1; + } + + if (container_is_removal_in_progress(cont->state) || container_is_dead(cont->state)) { + ERROR("Container is marked for removal and cannot be \"update\"."); + isulad_set_error_message( + "Cannot update container %s: Container is marked for removal and cannot be \"update\".", id); +- ret = -1; +- goto out; ++ return -1; + } + + if (container_is_running(cont->state) && hostconfig->kernel_memory) { +@@ -1129,12 +1128,17 @@ static int update_host_config_check(container_t *cont, host_config *hostconfig) + isulad_set_error_message("Cannot update container %s: Can not update kernel memory to a running container," + " please stop it first.", + id); +- ret = -1; +- goto out; ++ return -1; + } + +-out: +- return ret; ++ if (cont->hostconfig->auto_remove && hostconfig->restart_policy != NULL && ++ hostconfig->restart_policy->name != NULL && strcmp("no", hostconfig->restart_policy->name) != 0) { ++ ERROR("Cannot update restart policy for the auto remove container %s", id); ++ isulad_set_error_message("Cannot update restart policy for the auto remove container %s", id); ++ return -1; ++ } ++ ++ return 0; + } + + static int do_update_resources(const container_update_request *request, container_t *cont) +-- +2.42.0 + diff --git a/0022-add-update-restart-policy-test.patch b/0022-add-update-restart-policy-test.patch new file mode 100644 index 0000000..1f324ae --- /dev/null +++ b/0022-add-update-restart-policy-test.patch @@ -0,0 +1,57 @@ +From 6815aec33caedaacba3b392ee5a2e5088fdf1faa Mon Sep 17 00:00:00 2001 +From: zhangxiaoyu +Date: Tue, 21 Nov 2023 10:24:26 +0800 +Subject: [PATCH 22/64] add update restart policy test + +Signed-off-by: zhangxiaoyu +--- + CI/test_cases/container_cases/update.sh | 26 +++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/CI/test_cases/container_cases/update.sh b/CI/test_cases/container_cases/update.sh +index d379acc2..29543e7c 100755 +--- a/CI/test_cases/container_cases/update.sh ++++ b/CI/test_cases/container_cases/update.sh +@@ -138,6 +138,27 @@ function do_test_t() + return $TC_RET_T + } + ++function test_autoremove_restartpolicy() ++{ ++ containername=test_update2 ++ containerid=`isula run -itd --runtime $1 --rm --name $containername busybox` ++ fn_check_eq "$?" "0" "run failed" ++ ++ isula update --restart always $containerid ++ fn_check_ne "$?" "0" "update should fail" ++ ++ isula update --restart nooooooooooo $containerid ++ fn_check_ne "$?" "0" "update should fail" ++ ++ isula update --restart no $containerid ++ fn_check_eq "$?" "0" "update restart policy no failed" ++ ++ isula rm -f $containername ++ fn_check_eq "$?" "0" "rm failed" ++ ++ return $TC_RET_T ++} ++ + function do_test_t1() + { + containername=test_update1 +@@ -173,6 +194,11 @@ do + let "ret=$ret + 1" + fi + ++ test_autoremove_restartpolicy $element ++ if [ $? -ne 0 ];then ++ let "ret=$ret + 1" ++ fi ++ + if [ -f "/sys/fs/cgroup/memory/memory.memsw.usage_in_bytes" ];then + do_test_t1 $element + if [ $? -ne 0 ];then +-- +2.42.0 + diff --git a/0023-2260-bugfix-for-rebuild-config.patch b/0023-2260-bugfix-for-rebuild-config.patch new file mode 100644 index 0000000..e5ce564 --- /dev/null +++ b/0023-2260-bugfix-for-rebuild-config.patch @@ -0,0 +1,73 @@ +From f08072a865fcf6191d65e7c01e11b99049758c57 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Tue, 21 Nov 2023 03:27:31 +0000 +Subject: [PATCH 23/64] !2260 bugfix for rebuild config * bugfix for rebuild + config + +--- + src/daemon/modules/container/restore/restore.c | 1 - + src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c | 5 +---- + src/daemon/modules/runtime/runtime.c | 5 +---- + 3 files changed, 2 insertions(+), 9 deletions(-) + +diff --git a/src/daemon/modules/container/restore/restore.c b/src/daemon/modules/container/restore/restore.c +index f6218fe6..a60b1410 100644 +--- a/src/daemon/modules/container/restore/restore.c ++++ b/src/daemon/modules/container/restore/restore.c +@@ -24,7 +24,6 @@ + #include + #include + #include +-#include + + #include "isulad_config.h" + +diff --git a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c +index 2f42909b..8f7211d7 100644 +--- a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c ++++ b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c +@@ -782,7 +782,6 @@ int rt_lcr_rebuild_config(const char *name, const char *runtime, const rt_rebuil + char oci_config_file[PATH_MAX] = { 0 }; + struct engine_operation *engine_ops = NULL; + oci_runtime_spec *oci_spec = NULL; +- __isula_auto_free char *json_container = NULL; + __isula_auto_free parser_error err = NULL; + + engine_ops = engines_get_handler(runtime); +@@ -836,9 +835,7 @@ int rt_lcr_rebuild_config(const char *name, const char *runtime, const rt_rebuil + WARN("Failed to rename backup old config to config for container %s", name); + } + } +- +- ret = 0; +- ++ ret = nret != 0 ? -1 : 0; + out: + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { + engine_ops->engine_clear_errmsg_op(); +diff --git a/src/daemon/modules/runtime/runtime.c b/src/daemon/modules/runtime/runtime.c +index d9a332af..4a239f0a 100644 +--- a/src/daemon/modules/runtime/runtime.c ++++ b/src/daemon/modules/runtime/runtime.c +@@ -470,7 +470,6 @@ out: + + int runtime_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params) + { +- int ret = 0; + const struct rt_ops *ops = NULL; + + if (name == NULL || runtime == NULL || params == NULL) { +@@ -484,9 +483,7 @@ int runtime_rebuild_config(const char *name, const char *runtime, const rt_rebui + return -1; + } + +- ret = ops->rt_rebuild_config(name, runtime, params); +- +- return ret; ++ return ops->rt_rebuild_config(name, runtime, params); + } + + int runtime_resize(const char *name, const char *runtime, const rt_resize_params_t *params) +-- +2.42.0 + diff --git a/0024-2170-isula-image-pull.patch b/0024-2170-isula-image-pull.patch new file mode 100644 index 0000000..534c2c5 --- /dev/null +++ b/0024-2170-isula-image-pull.patch @@ -0,0 +1,1815 @@ +From 53d551f613bfa8ce0552ca62f964a0584e3665bb Mon Sep 17 00:00:00 2001 +From: sailorvii +Date: Wed, 22 Nov 2023 01:22:04 +0000 +Subject: [PATCH 24/64] =?UTF-8?q?!2170=20=E5=A2=9E=E5=8A=A0isula=20image?= + =?UTF-8?q?=20pull=E8=BF=9B=E5=BA=A6=E6=98=BE=E7=A4=BA=20*=20Refine=20some?= + =?UTF-8?q?=20issues.=20*=20Address=20comment=20*=20Address=20comments=20*?= + =?UTF-8?q?=201.=20Address=20comments.=20*=20Address=20comments=20*=20Addr?= + =?UTF-8?q?ess=20comments=20*=20Address=20comments=20*=20Address=20comment?= + =?UTF-8?q?s=20*=20Address=20comments=20*=20Address=20comments=20*=20Addre?= + =?UTF-8?q?ss=20comments=20*=20Address=20comments=20*=20Address=20comments?= + =?UTF-8?q?=20*=20Address=20test=20issue=20*=20Address=20test=20compile=20?= + =?UTF-8?q?issue=20*=20Address=20compile=20issue=20*=20Fix=20compile=20iss?= + =?UTF-8?q?ue=20*=20Address=20comments=20*=20Address=20comments=20*=20Addr?= + =?UTF-8?q?ess=20comments.=20*=20Address=20issuse=20*=20Address=20many=20i?= + =?UTF-8?q?ssues.=20*=20Fix=20some=20minor=20issuses.=20*=20Address=20comm?= + =?UTF-8?q?ents.=20*=20Refine=20as=20Haozi's=20comments=20*=20Fix=20some?= + =?UTF-8?q?=20issues=20by=20Haozi's=20comments.=20*=20Refine=20formats.=20?= + =?UTF-8?q?*=20Add=20process=20bar=20show=20for=20pull=20functions.?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + CI/dockerfiles/Dockerfile-fedora | 2 +- + CI/pr-gateway.sh | 2 +- + cmake/checker.cmake | 10 ++ + src/CMakeLists.txt | 4 + + src/api/services/images/images.proto | 35 +++- + src/client/connect/grpc/grpc_images_client.cc | 167 ++++++++++++++++-- + src/client/connect/protocol_type.h | 1 + + src/cmd/isula/images/pull.c | 26 ++- + .../connect/grpc/grpc_containers_service.h | 4 + + .../entry/connect/grpc/grpc_images_service.cc | 105 ++++++++++- + .../entry/connect/grpc/grpc_images_service.h | 7 + + .../entry/connect/rest/rest_images_service.c | 2 +- + .../v1/v1_cri_image_manager_service_impl.cc | 2 +- + .../v1alpha/cri_image_manager_service_impl.cc | 2 +- + src/daemon/executor/callback.h | 3 +- + src/daemon/executor/image_cb/image_cb.c | 8 +- + src/daemon/modules/api/image_api.h | 5 +- + src/daemon/modules/image/image.c | 9 +- + src/daemon/modules/image/oci/oci_image.c | 4 +- + src/daemon/modules/image/oci/oci_image.h | 2 +- + src/daemon/modules/image/oci/oci_pull.c | 158 +++++++++++++++-- + src/daemon/modules/image/oci/oci_pull.h | 2 +- + src/daemon/modules/image/oci/progress.c | 124 +++++++++++++ + src/daemon/modules/image/oci/progress.h | 52 ++++++ + .../modules/image/oci/registry/http_request.c | 104 ++++++++--- + .../modules/image/oci/registry/http_request.h | 2 +- + .../modules/image/oci/registry/registry.c | 3 +- + .../modules/image/oci/registry/registry.h | 2 + + .../image/oci/registry/registry_apiv2.c | 12 +- + src/daemon/modules/image/oci/registry_type.h | 3 + + src/utils/CMakeLists.txt | 3 + + src/utils/http/http.h | 17 +- + src/utils/progress/CMakeLists.txt | 13 ++ + src/utils/progress/show.c | 64 +++++++ + src/utils/progress/show.h | 34 ++++ + test/cutils/CMakeLists.txt | 1 + + test/image/oci/registry/CMakeLists.txt | 1 + + test/image/oci/registry/registry_ut.cc | 16 +- + 38 files changed, 912 insertions(+), 99 deletions(-) + create mode 100644 src/daemon/modules/image/oci/progress.c + create mode 100644 src/daemon/modules/image/oci/progress.h + create mode 100644 src/utils/progress/CMakeLists.txt + create mode 100644 src/utils/progress/show.c + create mode 100644 src/utils/progress/show.h + +diff --git a/CI/dockerfiles/Dockerfile-fedora b/CI/dockerfiles/Dockerfile-fedora +index bef44377..a105cbb4 100644 +--- a/CI/dockerfiles/Dockerfile-fedora ++++ b/CI/dockerfiles/Dockerfile-fedora +@@ -115,7 +115,7 @@ RUN echo "[source.crates-io]" >> ${HOME}/.cargo/config && \ + echo "[source.local-registry]" >> ${HOME}/.cargo/config && \ + echo "directory = \"vendor\"" >> ${HOME}/.cargo/config + +-RUN dnf install -y lcov && dnf clean all ++RUN dnf install -y lcov ncurses-devel && dnf clean all + + # install libevhtp + RUN export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH && \ +diff --git a/CI/pr-gateway.sh b/CI/pr-gateway.sh +index 08bcfc4f..e5bf627e 100755 +--- a/CI/pr-gateway.sh ++++ b/CI/pr-gateway.sh +@@ -22,7 +22,7 @@ sed -i "s#http://repo.openeuler.org#https://repo.huaweicloud.com/openeuler#g" /e + + dnf update -y + +-dnf install -y docbook2X doxygen gtest-devel gmock-devel diffutils cmake gcc-c++ yajl-devel patch make libtool libevent-devel libevhtp-devel grpc grpc-plugins grpc-devel protobuf-devel libcurl libcurl-devel sqlite-devel libarchive-devel device-mapper-devel http-parser-devel libseccomp-devel libcap-devel libselinux-devel libwebsockets libwebsockets-devel systemd-devel git chrpath ++dnf install -y docbook2X doxygen gtest-devel gmock-devel diffutils cmake gcc-c++ yajl-devel patch make libtool libevent-devel libevhtp-devel grpc grpc-plugins grpc-devel protobuf-devel libcurl libcurl-devel sqlite-devel libarchive-devel device-mapper-devel http-parser-devel libseccomp-devel libcap-devel libselinux-devel libwebsockets libwebsockets-devel systemd-devel git chrpath ncurses-devel + if [ $? -ne 0 ]; then + echo "install dependences failed" + exit 1 +diff --git a/cmake/checker.cmake b/cmake/checker.cmake +index 358ab4af..cc4a1fc3 100644 +--- a/cmake/checker.cmake ++++ b/cmake/checker.cmake +@@ -154,6 +154,16 @@ if (GRPC_CONNECTOR) + _CHECK(WEBSOCKET_INCLUDE_DIR "WEBSOCKET_INCLUDE_DIR-NOTFOUND" libwebsockets.h) + find_library(WEBSOCKET_LIBRARY websockets) + _CHECK(WEBSOCKET_LIBRARY "WEBSOCKET_LIBRARY-NOTFOUND" "libwebsockets.so") ++ ++ # check libncurses ++ pkg_check_modules(PC_LIBNCURSES REQUIRED "ncurses") ++ find_path(NCURSES_INCLUDE_DIR curses.h ++ HINTS ${PC_NCURSES_INCLUDEDIR} ${PC_NCURSES_INCLUDE_DIRS}) ++ _CHECK(NCURSES_INCLUDE_DIR "NCURSES_INCLUDE_DIR-NOTFOUND" "curses.h") ++ ++ find_library(NCURSES_LIBRARY ncurses ++ HINTS ${PC_NCURSES_LIBDIR} ${PC_NCURSES_LIBRARY_DIRS}) ++ _CHECK(NCURSES_LIBRARY "NCURSES_LIBRARY-NOTFOUND" "libncurses.so") + endif() + + if ((NOT GRPC_CONNECTOR) OR (GRPC_CONNECTOR AND ENABLE_METRICS)) +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 8e197b9f..860447de 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -102,6 +102,10 @@ add_executable(isula + ) + target_include_directories(isula PUBLIC ${ISULA_INCS} ${SHARED_INCS}) + target_link_libraries(isula libisula_client ${LIBYAJL_LIBRARY}) ++if (GRPC_CONNECTOR) ++ target_link_libraries(isula ${NCURSES_LIBRARY}) ++endif() ++ + if (ANDROID OR MUSL) + target_link_libraries(isula ${LIBSSL_LIBRARY}) + else() +diff --git a/src/api/services/images/images.proto b/src/api/services/images/images.proto +index 2a34f02d..9f2cb803 100644 +--- a/src/api/services/images/images.proto ++++ b/src/api/services/images/images.proto +@@ -30,6 +30,23 @@ service ImagesService { + rpc Tag(TagImageRequest) returns (TagImageResponse); + rpc Import(ImportRequest) returns (ImportResponse); + rpc Search(SearchRequest) returns (SearchResponse); ++ rpc PullImage(PullImageRequest) returns (stream PullImageResponse); ++} ++ ++// ImageSpec is an internal representation of an image. ++message ImageSpec { ++ // Container's Image field (e.g. imageID or imageDigest). ++ string image = 1; ++ // Unstructured key-value map holding arbitrary metadata. ++ // ImageSpec Annotations can be used to help the runtime target specific ++ // images in multi-arch images. ++ map annotations = 2; ++} ++ ++// AuthConfig contains authorization information for connecting to a registry. ++message AuthConfig { ++ string username = 1; ++ string password = 2; + } + + message Descriptor { +@@ -152,4 +169,20 @@ message SearchResponse { + repeated SearchImage search_result = 2; + uint32 cc = 3; + string errmsg = 4; +-} +\ No newline at end of file ++} ++ ++message PullImageRequest { ++ // Spec of the image. ++ ImageSpec image = 1; ++ // Authentication configuration for pulling the image. ++ AuthConfig auth = 2; ++ bool is_progress_visible = 3; ++} ++ ++message PullImageResponse { ++ // Reference to the image in use. For most runtimes, this should be an ++ // image ID or digest. ++ string image_ref = 1; ++ string stream = 2; ++ bytes progress_data = 3; ++} +diff --git a/src/client/connect/grpc/grpc_images_client.cc b/src/client/connect/grpc/grpc_images_client.cc +index 9cc2a174..7a283e8c 100644 +--- a/src/client/connect/grpc/grpc_images_client.cc ++++ b/src/client/connect/grpc/grpc_images_client.cc +@@ -13,12 +13,15 @@ + * Description: provide grpc container service functions + ******************************************************************************/ + #include "grpc_images_client.h" +-#include "api.grpc.pb.h" + #include "client_base.h" + #include "images.grpc.pb.h" ++ ++#include ++#include ++#include ++#include "show.h" + #include "utils.h" + #include "constants.h" +-#include + + using namespace images; + +@@ -337,9 +340,9 @@ public: + } + }; + +-class ImagesPull : public ClientBase { ++class ImagesPull : public ClientBase { + public: + explicit ImagesPull(void *args) + : ClientBase(args) +@@ -347,15 +350,14 @@ public: + } + ~ImagesPull() = default; + +- auto request_to_grpc(const isula_pull_request *request, runtime::v1alpha2::PullImageRequest *grequest) ++ auto request_to_grpc(const isula_pull_request *request, PullImageRequest *grequest) + -> int override + { + if (request == nullptr) { + return -1; + } +- + if (request->image_name != nullptr) { +- auto *image_spec = new (std::nothrow) runtime::v1alpha2::ImageSpec; ++ auto *image_spec = new (std::nothrow) ImageSpec; + if (image_spec == nullptr) { + return -1; + } +@@ -363,10 +365,12 @@ public: + grequest->set_allocated_image(image_spec); + } + ++ grequest->set_is_progress_visible(request->is_progress_visible); ++ + return 0; + } + +- auto response_from_grpc(runtime::v1alpha2::PullImageResponse *gresponse, isula_pull_response *response) ++ auto response_from_grpc(PullImageResponse *gresponse, isula_pull_response *response) + -> int override + { + if (!gresponse->image_ref().empty()) { +@@ -376,7 +380,7 @@ public: + return 0; + } + +- auto check_parameter(const runtime::v1alpha2::PullImageRequest &req) -> int override ++ auto check_parameter(const PullImageRequest &req) -> int override + { + if (req.image().image().empty()) { + ERROR("Missing image name in the request"); +@@ -386,10 +390,147 @@ public: + return 0; + } + +- auto grpc_call(ClientContext *context, const runtime::v1alpha2::PullImageRequest &req, +- runtime::v1alpha2::PullImageResponse *reply) -> Status override ++ auto run(const struct isula_pull_request *request, struct isula_pull_response *response) -> int override ++ { ++ ClientContext context; ++ PullImageRequest grequest; ++ ++#ifdef ENABLE_GRPC_REMOTE_CONNECT ++#ifdef OPENSSL_VERIFY ++ // Set common name from cert.perm ++ char common_name_value[ClientBaseConstants::COMMON_NAME_LEN] = { 0 }; ++ int ret = get_common_name_from_tls_cert(m_certFile.c_str(), common_name_value, ++ ClientBaseConstants::COMMON_NAME_LEN); ++ if (ret != 0) { ++ ERROR("Failed to get common name in: %s", m_certFile.c_str()); ++ return -1; ++ } ++ context.AddMetadata("username", std::string(common_name_value, strlen(common_name_value))); ++ context.AddMetadata("tls_mode", m_tlsMode); ++#endif ++#endif ++ if (request_to_grpc(request, &grequest) != 0) { ++ ERROR("Failed to transform pull request to grpc"); ++ response->server_errono = ISULAD_ERR_INPUT; ++ return -1; ++ } ++ ++ auto reader = stub_->PullImage(&context, grequest); ++ ++ PullImageResponse gresponse; ++ if (grequest.is_progress_visible()) { ++ while (reader->Read(&gresponse)) { ++ output_progress(gresponse); ++ } ++ } else { ++ reader->Read(&gresponse); ++ WARN("The terminal may not support ANSI Escape code. Display is skipped"); ++ } ++ Status status = reader->Finish(); ++ if (!status.ok()) { ++ ERROR("Error code: %d: %s", status.error_code(), status.error_message().c_str()); ++ unpackStatus(status, response); ++ return -1; ++ } ++ response->image_ref = util_strdup_s(gresponse.image_ref().c_str()); ++ return 0; ++ } ++ ++private: ++ void output_progress(PullImageResponse &gresponse) + { +- return stub_->PullImage(context, req, reply); ++ __isula_auto_free char *err = nullptr; ++ struct parser_context ctx = { OPT_GEN_SIMPLIFY, 0 }; ++ ++ image_progress *progresses = image_progress_parse_data(gresponse.progress_data().c_str(), &ctx, &err); ++ if (progresses == nullptr) { ++ ERROR("Parse image progress error %s", err); ++ return; ++ } ++ show_processes(progresses); ++ } ++ ++ void get_printed_value(int64_t value, char *printed) ++ { ++ float float_value = 0.0; ++ const float GB = 1024 * 1024 * 1024; ++ const float MB = 1024 * 1024; ++ const float KB = 1024; ++ ++ if ((float)value / GB > 1) { ++ float_value = (float)value / GB; ++ sprintf(printed, "%.2fGB", float_value); ++ } else if ((float)value / MB > 1) { ++ float_value = (float)value / MB; ++ sprintf(printed, "%.2fMB", float_value); ++ } else if ((float)value / KB > 1) { ++ float_value = (float)value / KB; ++ sprintf(printed, "%.2fKB", float_value); ++ } else { ++ sprintf(printed, "%ldB", value); ++ } ++ } ++ ++ void display_progress_bar(image_progress_progresses_element *progress_item, int width, bool if_show_all) ++ { ++ float progress = 0.0; ++ int filled_width = 0; ++ const int FLOAT_STRING_SIZE = 64; ++ char total[FLOAT_STRING_SIZE] = {0}; ++ char current[FLOAT_STRING_SIZE] = {0}; ++ int empty_width = 0; ++ ++ if (progress_item->total != 0) { ++ progress = (float)progress_item->current / (float)progress_item->total; ++ } ++ filled_width = (int)(progress * width); ++ empty_width = width - filled_width; ++ get_printed_value(progress_item->total, total); ++ get_printed_value(progress_item->current, current); ++ ++ if (if_show_all) { ++ int i = 0; ++ ++ printf("%s: [", progress_item->id); ++ ++ // Print filled characters ++ for (i = 0; i < filled_width; i++) { ++ printf("="); ++ } ++ printf(">"); ++ // Print empty characters ++ for (i = 0; i < empty_width; i++) { ++ printf(" "); ++ } ++ ++ printf("] %s/%s", current, total); ++ } else { ++ printf("%s: %s/%s", progress_item->id, current, total); ++ } ++ printf("\n"); ++ fflush(stdout); ++ } ++ ++ void show_processes(image_progress *progresses) ++ { ++ size_t i = 0; ++ static size_t len = 0; ++ const int TERMINAL_SHOW_WIDTH = 110; ++ const int width = 50; // Width of the progress bars ++ ++ if (len != 0) { ++ move_cursor_up(len); ++ } ++ clear_lines_below(); ++ len = progresses->progresses_len; ++ int terminal_width = get_terminal_width(); ++ bool if_show_all = true; ++ if (terminal_width < TERMINAL_SHOW_WIDTH) { ++ if_show_all = false; ++ } ++ for (i = 0; i < len; i++) { ++ display_progress_bar(progresses->progresses[i], width, if_show_all); ++ } + } + }; + +diff --git a/src/client/connect/protocol_type.h b/src/client/connect/protocol_type.h +index 4206c50b..2b445c5a 100644 +--- a/src/client/connect/protocol_type.h ++++ b/src/client/connect/protocol_type.h +@@ -479,6 +479,7 @@ struct isula_rmi_response { + + struct isula_pull_request { + char *image_name; ++ bool is_progress_visible; + }; + + struct isula_tag_request { +diff --git a/src/cmd/isula/images/pull.c b/src/cmd/isula/images/pull.c +index 548e8d90..9d420778 100644 +--- a/src/cmd/isula/images/pull.c ++++ b/src/cmd/isula/images/pull.c +@@ -14,6 +14,10 @@ + ********************************************************************************/ + #include "pull.h" + ++#ifdef GRPC_CONNECTOR ++#include ++#include ++#endif + #include + #include + +@@ -29,6 +33,25 @@ const char g_cmd_pull_usage[] = "pull [OPTIONS] NAME[:TAG]"; + + struct client_arguments g_cmd_pull_args = {}; + ++static bool is_terminal_show_supported() ++{ ++#ifdef GRPC_CONNECTOR ++ // Initialize the terminfo database ++ setupterm(NULL, STDOUT_FILENO, (int *)0); ++ ++ // Query the database for the capability to move the cursor ++ char *cursor_movement = tgetstr("cm", NULL); ++ ++ if (cursor_movement != NULL) { ++ return true; ++ } else { ++ return false; ++ } ++#else ++ return false; ++#endif ++} ++ + /* + * Pull an image or a repository from a registry + */ +@@ -47,6 +70,7 @@ int client_pull(const struct client_arguments *args) + } + + request.image_name = args->image_name; ++ request.is_progress_visible = is_terminal_show_supported(); + + ops = get_connect_client_ops(); + if (ops == NULL || ops->image.pull == NULL) { +@@ -63,8 +87,8 @@ int client_pull(const struct client_arguments *args) + ret = ESERVERERROR; + goto out; + } +- COMMAND_ERROR("Image \"%s\" pulled", response->image_ref); + ++ COMMAND_ERROR("Image \"%s\" pulled", response->image_ref); + out: + isula_pull_response_free(response); + return ret; +diff --git a/src/daemon/entry/connect/grpc/grpc_containers_service.h b/src/daemon/entry/connect/grpc/grpc_containers_service.h +index 92428fbe..4a6c584b 100644 +--- a/src/daemon/entry/connect/grpc/grpc_containers_service.h ++++ b/src/daemon/entry/connect/grpc/grpc_containers_service.h +@@ -37,6 +37,10 @@ using google::protobuf::Timestamp; + void protobuf_timestamp_to_grpc(types_timestamp_t *timestamp, Timestamp *gtimestamp); + void protobuf_timestamp_from_grpc(types_timestamp_t *timestamp, const Timestamp >imestamp); + ++bool grpc_is_call_cancelled(void *context); ++bool grpc_add_initial_metadata(void *context, const char *header, const char *val); ++bool grpc_event_write_function(void *writer, void *data); ++ + // Implement of containers service + class ContainerServiceImpl final : public ContainerService::Service { + public: +diff --git a/src/daemon/entry/connect/grpc/grpc_images_service.cc b/src/daemon/entry/connect/grpc/grpc_images_service.cc +index 5d3fac6b..406f81a9 100644 +--- a/src/daemon/entry/connect/grpc/grpc_images_service.cc ++++ b/src/daemon/entry/connect/grpc/grpc_images_service.cc +@@ -21,9 +21,12 @@ + #include + #include + +-#include "isula_libutils/log.h" ++#include ++#include ++#include + #include "utils.h" + #include "grpc_server_tls_auth.h" ++#include "grpc_containers_service.h" + + int ImagesServiceImpl::image_list_request_from_grpc(const ListImagesRequest *grequest, + image_list_images_request **request) +@@ -596,6 +599,104 @@ Status ImagesServiceImpl::Logout(ServerContext *context, const LogoutRequest *re + return Status::OK; + } + ++int ImagesServiceImpl::image_pull_request_from_grpc(const PullImageRequest *grequest, ++ image_pull_image_request **request) ++{ ++ auto *tmpreq = (image_pull_image_request *)util_common_calloc_s(sizeof(image_pull_image_request)); ++ if (tmpreq == nullptr) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ ++ if (!grequest->image().image().empty()) { ++ tmpreq->image_name = util_strdup_s(grequest->image().image().c_str()); ++ } ++ tmpreq->is_progress_visible = grequest->is_progress_visible(); ++ *request = tmpreq; ++ ++ return 0; ++} ++ ++void image_pull_progress_to_grpc(const image_progress *progress, ++ PullImageResponse &gresponse) ++{ ++ if (progress == nullptr) { ++ ERROR("Invalid parameter"); ++ return; ++ } ++ ++ gresponse.Clear(); ++ __isula_auto_free char *err = nullptr; ++ struct parser_context ctx = { OPT_GEN_SIMPLIFY, 0 }; ++ char *data = image_progress_generate_json(progress, &ctx, &err); ++ if (data == nullptr) { ++ ERROR("Failed to generate image progress json: %s", err); ++ return; ++ } ++ ++ gresponse.set_progress_data(data, strlen(data)); ++ if (progress->image != nullptr) { ++ gresponse.set_image_ref(progress->image); ++ } ++ free(data); ++} ++ ++bool grpc_pull_write_function(void *writer, void *data) ++{ ++ auto *progress = static_cast(data); ++ auto *gwriter = static_cast *>(writer); ++ PullImageResponse gresponse; ++ ++ image_pull_progress_to_grpc(progress, gresponse); ++ ++ return gwriter->Write(gresponse); ++} ++ ++Status ImagesServiceImpl::PullImage(ServerContext *context, const PullImageRequest *request, ++ ServerWriter *writer) ++{ ++ prctl(PR_SET_NAME, "RegistryPull"); ++ ++ int ret = 0; ++ std::string errmsg = "Failed to execute image pull"; ++ stream_func_wrapper stream = { 0 }; ++ image_pull_image_request *image_req = nullptr; ++ image_pull_image_response *image_res = nullptr; ++ ++ if (context == nullptr || request == nullptr || writer == nullptr) { ++ return Status(StatusCode::INVALID_ARGUMENT, "Invalid argument"); ++ } ++ ++ auto status = GrpcServerTlsAuth::auth(context, "pull"); ++ if (!status.ok()) { ++ return status; ++ } ++ ++ service_executor_t *cb = get_service_executor(); ++ if (cb == nullptr || cb->image.pull == nullptr) { ++ return Status(StatusCode::UNIMPLEMENTED, "Unimplemented callback"); ++ } ++ ++ ret = image_pull_request_from_grpc(request, &image_req); ++ if (ret != 0) { ++ ERROR("Failed to transform grpc request"); ++ return Status(StatusCode::UNKNOWN, "Failed to transform grpc request"); ++ } ++ ++ stream.context = (void *)context; ++ stream.is_cancelled = &grpc_is_call_cancelled; ++ stream.write_func = &grpc_pull_write_function; ++ stream.writer = (void *)writer; ++ ++ ret = cb->image.pull(image_req, &stream, &image_res); ++ free_image_pull_image_request(image_req); ++ free_image_pull_image_response(image_res); ++ if (ret == 0) { ++ return Status::OK; ++ } ++ return Status(StatusCode::UNKNOWN, errmsg); ++} ++ + #ifdef ENABLE_IMAGE_SEARCH + int ImagesServiceImpl::search_request_from_grpc(const SearchRequest *grequest, image_search_images_request **request) + { +@@ -723,4 +824,4 @@ Status ImagesServiceImpl::Search(ServerContext *context, const SearchRequest *re + + return Status::OK; + } +-#endif +\ No newline at end of file ++#endif +diff --git a/src/daemon/entry/connect/grpc/grpc_images_service.h b/src/daemon/entry/connect/grpc/grpc_images_service.h +index b75075ba..9690f544 100644 +--- a/src/daemon/entry/connect/grpc/grpc_images_service.h ++++ b/src/daemon/entry/connect/grpc/grpc_images_service.h +@@ -58,6 +58,9 @@ public: + + Status Logout(ServerContext *context, const LogoutRequest *request, LogoutResponse *reply) override; + ++ Status PullImage(ServerContext *context, const PullImageRequest *request, ++ ServerWriter *writer) override; ++ + #ifdef ENABLE_IMAGE_SEARCH + Status Search(ServerContext *context, const SearchRequest *request, SearchResponse *reply) override; + #endif +@@ -99,6 +102,10 @@ private: + + int image_logout_request_from_grpc(const LogoutRequest *grequest, image_logout_request **request); + ++ int image_pull_request_from_grpc(const PullImageRequest *grequest, image_pull_image_request **request); ++ ++ void image_pull_response_to_grpc(const image_pull_image_response *response, PullImageResponse *gresponse); ++ + #ifdef ENABLE_IMAGE_SEARCH + int search_request_from_grpc(const SearchRequest *grequest, image_search_images_request **request); + +diff --git a/src/daemon/entry/connect/rest/rest_images_service.c b/src/daemon/entry/connect/rest/rest_images_service.c +index 5a719f83..220de399 100644 +--- a/src/daemon/entry/connect/rest/rest_images_service.c ++++ b/src/daemon/entry/connect/rest/rest_images_service.c +@@ -513,7 +513,7 @@ static void rest_image_pull_cb(evhtp_request_t *req, void *arg) + goto out; + } + +- (void)cb->image.pull(crequest, &cresponse); ++ (void)cb->image.pull(crequest, NULL, &cresponse); + + evhtp_send_image_pull_repsponse(req, cresponse, RESTFUL_RES_OK); + +diff --git a/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.cc b/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.cc +index b74834fb..b9cbf24c 100644 +--- a/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.cc ++++ b/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.cc +@@ -265,7 +265,7 @@ auto ImageManagerServiceImpl::PullImage(const runtime::v1::ImageSpec &image, + } + request->type = util_strdup_s(IMAGE_TYPE_OCI); + +- ret = im_pull_image(request, &response); ++ ret = im_pull_image(request, nullptr, &response); + if (ret != 0) { + if (response != nullptr && response->errmsg != nullptr) { + error.SetError(response->errmsg); +diff --git a/src/daemon/entry/cri/v1alpha/cri_image_manager_service_impl.cc b/src/daemon/entry/cri/v1alpha/cri_image_manager_service_impl.cc +index 3ff79ffc..0b36f007 100644 +--- a/src/daemon/entry/cri/v1alpha/cri_image_manager_service_impl.cc ++++ b/src/daemon/entry/cri/v1alpha/cri_image_manager_service_impl.cc +@@ -265,7 +265,7 @@ auto ImageManagerServiceImpl::PullImage(const runtime::v1alpha2::ImageSpec &imag + } + request->type = util_strdup_s(IMAGE_TYPE_OCI); + +- ret = im_pull_image(request, &response); ++ ret = im_pull_image(request, NULL, &response); + if (ret != 0) { + if (response != nullptr && response->errmsg != nullptr) { + error.SetError(response->errmsg); +diff --git a/src/daemon/executor/callback.h b/src/daemon/executor/callback.h +index c48253a1..b32c6b27 100644 +--- a/src/daemon/executor/callback.h ++++ b/src/daemon/executor/callback.h +@@ -285,7 +285,8 @@ typedef struct { + int (*logout)(const image_logout_request *request, image_logout_response **response); + + int (*tag)(const image_tag_image_request *request, image_tag_image_response **response); +- int (*pull)(const image_pull_image_request *request, image_pull_image_response **response); ++ ++ int (*pull)(const image_pull_image_request *request, stream_func_wrapper *stream, image_pull_image_response **response); + #ifdef ENABLE_IMAGE_SEARCH + int (*search)(const image_search_images_request *request, image_search_images_response **response); + #endif +diff --git a/src/daemon/executor/image_cb/image_cb.c b/src/daemon/executor/image_cb/image_cb.c +index 61fa29db..317cb0a8 100644 +--- a/src/daemon/executor/image_cb/image_cb.c ++++ b/src/daemon/executor/image_cb/image_cb.c +@@ -955,12 +955,14 @@ int pull_request_from_rest(const image_pull_image_request *request, im_pull_requ + } + + (*im_req)->image = util_strdup_s(request->image_name); ++ (*im_req)->is_progress_visible = request->is_progress_visible; + + return 0; + } + + /* image pull cb */ +-static int image_pull_cb(const image_pull_image_request *request, image_pull_image_response **response) ++static int image_pull_cb(const image_pull_image_request *request, stream_func_wrapper *stream, ++ image_pull_image_response **response) + { + int ret = -1; + im_pull_request *im_req = NULL; +@@ -988,7 +990,7 @@ static int image_pull_cb(const image_pull_image_request *request, image_pull_ima + + // current only oci image support pull + im_req->type = util_strdup_s(IMAGE_TYPE_OCI); +- ret = im_pull_image(im_req, &im_rsp); ++ ret = im_pull_image(im_req, stream, &im_rsp); + if (ret != 0) { + cc = ISULAD_ERR_EXEC; + goto out; +@@ -1203,4 +1205,4 @@ void image_callback_init(service_image_callback_t *cb) + #ifdef ENABLE_IMAGE_SEARCH + cb->search = image_search_cb; + #endif +-} +\ No newline at end of file ++} +diff --git a/src/daemon/modules/api/image_api.h b/src/daemon/modules/api/image_api.h +index 2f2c00a2..bbe89ad7 100644 +--- a/src/daemon/modules/api/image_api.h ++++ b/src/daemon/modules/api/image_api.h +@@ -32,6 +32,7 @@ + #ifdef ENABLE_IMAGE_SEARCH + #include "isula_libutils/imagetool_search_result.h" + #endif ++#include "stream_wrapper.h" + + #ifdef __cplusplus + extern "C" { +@@ -150,6 +151,8 @@ typedef struct { + char *server_address; + char *identity_token; + char *registry_token; ++ ++ bool is_progress_visible; + } im_pull_request; + + typedef struct { +@@ -304,7 +307,7 @@ void free_im_load_request(im_load_request *ptr); + + void free_im_load_response(im_load_response *ptr); + +-int im_pull_image(const im_pull_request *request, im_pull_response **response); ++int im_pull_image(const im_pull_request *request, stream_func_wrapper *stream, im_pull_response **response); + + void free_im_pull_request(im_pull_request *req); + +diff --git a/src/daemon/modules/image/image.c b/src/daemon/modules/image/image.c +index a14f2ac3..8d7e2c1a 100644 +--- a/src/daemon/modules/image/image.c ++++ b/src/daemon/modules/image/image.c +@@ -86,7 +86,7 @@ struct bim_ops { + int (*load_image)(const im_load_request *request); + + /* pull image */ +- int (*pull_image)(const im_pull_request *request, im_pull_response *response); ++ int (*pull_image)(const im_pull_request *request, stream_func_wrapper *stream, im_pull_response *response); + + /* login */ + int (*login)(const im_login_request *request); +@@ -999,7 +999,7 @@ static bool check_im_pull_args(const im_pull_request *req, im_pull_response * co + return true; + } + +-int im_pull_image(const im_pull_request *request, im_pull_response **response) ++int im_pull_image(const im_pull_request *request, stream_func_wrapper *stream, im_pull_response **response) + { + int ret = -1; + struct bim *bim = NULL; +@@ -1029,7 +1029,7 @@ int im_pull_image(const im_pull_request *request, im_pull_response **response) + } + + EVENT("Event: {Object: %s, Type: Pulling}", request->image); +- ret = bim->ops->pull_image(request, tmp_res); ++ ret = bim->ops->pull_image(request, stream, tmp_res); + if (ret != 0) { + ERROR("Pull image %s failed", request->image); + ret = -1; +@@ -1044,6 +1044,7 @@ out: + } + DAEMON_CLEAR_ERRMSG(); + *response = tmp_res; ++ + return ret; + } + +@@ -2395,4 +2396,4 @@ out: + } + return ret; + } +-#endif +\ No newline at end of file ++#endif +diff --git a/src/daemon/modules/image/oci/oci_image.c b/src/daemon/modules/image/oci/oci_image.c +index f712a446..471510e7 100644 +--- a/src/daemon/modules/image/oci/oci_image.c ++++ b/src/daemon/modules/image/oci/oci_image.c +@@ -359,7 +359,7 @@ void oci_exit(void) + free_oci_image_data(); + } + +-int oci_pull_rf(const im_pull_request *request, im_pull_response *response) ++int oci_pull_rf(const im_pull_request *request, stream_func_wrapper *stream, im_pull_response *response) + { + int ret = 0; + if (request == NULL || request->image == NULL || response == NULL) { +@@ -381,7 +381,7 @@ int oci_pull_rf(const im_pull_request *request, im_pull_response *response) + } + #endif + +- ret = oci_do_pull_image(request, response); ++ ret = oci_do_pull_image(request, stream, response); + + #ifdef ENABLE_REMOTE_LAYER_STORE + if (g_enable_remote) { +diff --git a/src/daemon/modules/image/oci/oci_image.h b/src/daemon/modules/image/oci/oci_image.h +index 07f10c8d..c7304897 100644 +--- a/src/daemon/modules/image/oci/oci_image.h ++++ b/src/daemon/modules/image/oci/oci_image.h +@@ -43,7 +43,7 @@ struct oci_image_module_data *get_oci_image_data(void); + int oci_init(const isulad_daemon_configs *args); + void oci_exit(void); + +-int oci_pull_rf(const im_pull_request *request, im_pull_response *response); ++int oci_pull_rf(const im_pull_request *request, stream_func_wrapper *stream, im_pull_response *response); + int oci_rmi(const im_rmi_request *request); + int oci_get_filesystem_info(im_fs_info_response **response); + int oci_load_image(const im_load_request *request); +diff --git a/src/daemon/modules/image/oci/oci_pull.c b/src/daemon/modules/image/oci/oci_pull.c +index e7ff77df..2706af91 100644 +--- a/src/daemon/modules/image/oci/oci_pull.c ++++ b/src/daemon/modules/image/oci/oci_pull.c +@@ -14,20 +14,25 @@ + *******************************************************************************/ + #include "oci_pull.h" + ++#include ++#include ++#include + #include + #include + #include ++#include + +-#include "isula_libutils/log.h" +-#include "utils.h" +-#include "utils_images.h" +-#include "registry.h" + #include "err_msg.h" ++#include "map.h" ++#include "oci_image.h" ++#include "progress.h" ++#include "registry.h" + #include "storage.h" ++#include "utils.h" + #include "utils_array.h" + #include "utils_base64.h" ++#include "utils_images.h" + #include "utils_string.h" +-#include "oci_image.h" + + static int decode_auth(const char *auth, char **username, char **password) + { +@@ -85,7 +90,7 @@ static void update_option_insecure_registry(registry_pull_options *options, char + } + } + +-static int pull_image(const im_pull_request *request, char **name) ++static int pull_image(const im_pull_request *request, progress_status_map *progress_status_store, char **name) + { + int ret = -1; + registry_pull_options *options = NULL; +@@ -112,6 +117,7 @@ static int pull_image(const im_pull_request *request, char **name) + options->auth.username = util_strdup_s(request->username); + options->auth.password = util_strdup_s(request->password); + } ++ options->progress_status_store = progress_status_store; + + oci_image_data = get_oci_image_data(); + options->skip_tls_verify = oci_image_data->insecure_skip_verify_enforce; +@@ -174,21 +180,131 @@ out: + return ret; + } + +-int oci_do_pull_image(const im_pull_request *request, im_pull_response *response) ++typedef struct status_arg { ++ progress_status_map *status_store; ++ bool should_terminal; ++ imagetool_image_summary *image; ++ char *image_name; ++ stream_func_wrapper *stream; ++} status_arg; ++ ++void *get_progress_status(void *arg) ++{ ++ status_arg *status = (status_arg *)arg; ++ const int delay = 100; // Sleep for 100 milliseconds ++ bool write_ok = false; ++ ++ if (status == NULL || status->status_store == NULL || status->stream == NULL) { ++ ERROR("Get progress status condition error"); ++ return NULL; ++ } ++ ++ for (;;) { ++ int i = 0; ++ ++ usleep(delay * 1000); // Sleep for 100 milliseconds ++ ++ if (status->should_terminal && status->image == NULL) { ++ break; ++ } ++ ++ image_progress *progresses; ++ size_t progress_size = progress_status_map_size(status->status_store); ++ ++ progresses = util_common_calloc_s(sizeof(image_progress)); ++ if (progresses == NULL) { ++ ERROR("Out of memory. Skip progress show."); ++ break; ++ } ++ ++ progresses->progresses = util_smart_calloc_s(sizeof(image_progress_progresses_element *), progress_size); ++ if (progresses->progresses == NULL) { ++ ERROR("Out of memory. Skip progress show."); ++ goto roundend; ++ } ++ if (status->image != NULL) { ++ progresses->image = util_strdup_s(status->image_name); ++ status->image = NULL; ++ } ++ ++ if (!progress_status_map_lock(status->status_store)) { ++ ERROR("Cannot itorate progress status map for locking failed"); ++ goto roundend; ++ } ++ map_itor *itor = map_itor_new(status->status_store->map); ++ for (i = 0; map_itor_valid(itor) && i < progress_size; map_itor_next(itor), i++) { ++ void *id = map_itor_key(itor); ++ const progress *value = (progress *)map_itor_value(itor); ++ const int ID_LEN = 12; // The last 12 charactos of image digest. ++ ++ progresses->progresses[i] = util_common_calloc_s(sizeof(image_progress_progresses_element)); ++ if (progresses->progresses[i] == NULL) { ++ WARN("Out of memory. Skip progress show."); ++ map_itor_free(itor); ++ progress_status_map_unlock(status->status_store); ++ goto roundend; ++ } ++ progresses->progresses[i]->id = util_strdup_s((char *)id + strlen((char *)id) - ID_LEN); ++ progresses->progresses[i]->total = value->dltotal; ++ progresses->progresses[i]->current = value->dlnow; ++ progresses->progresses_len++; ++ } ++ map_itor_free(itor); ++ progress_status_map_unlock(status->status_store); ++ ++ /* send to client */ ++ write_ok = status->stream->write_func(status->stream->writer, progresses); ++ if (write_ok) { ++ goto roundend; ++ } ++ if (status->stream->is_cancelled(status->stream->context)) { ++ ERROR("pull stream is cancelled"); ++ goto roundend; ++ } ++ ERROR("Send progress data to client failed"); ++roundend: ++ free_image_progress(progresses); ++ } ++ return NULL; ++} ++ ++int oci_do_pull_image(const im_pull_request *request, stream_func_wrapper *stream, im_pull_response *response) + { + int ret = 0; + imagetool_image_summary *image = NULL; + imagetool_image_summary *image2 = NULL; + char *dest_image_name = NULL; ++ progress_status_map *progress_status_store = NULL; + + if (request == NULL || request->image == NULL || response == NULL) { + ERROR("Invalid NULL param"); + return -1; + } + +- ret = pull_image(request, &dest_image_name); ++ pthread_t tid = 0; ++ status_arg arg = {0}; ++ if (request->is_progress_visible && stream != NULL) { ++ progress_status_store = progress_status_map_new(); ++ if (progress_status_store == NULL) { ++ ERROR("Out of memory and will not show the pull progress"); ++ isulad_set_error_message("Failed to pull image %s with error: out of memory", request->image); ++ ret = -1; ++ goto out; ++ } ++ arg.should_terminal = false; ++ arg.status_store = progress_status_store; ++ arg.stream = stream; ++ if (pthread_create(&tid, NULL, get_progress_status, (void *)&arg) != 0) { ++ ERROR("Failed to start thread to get progress status"); ++ isulad_set_error_message("Failed to pull image %s with error: start progress thread error", request->image); ++ ret = -1; ++ goto out; ++ } ++ } ++ ++ ret = pull_image(request, progress_status_store, &dest_image_name); + if (ret != 0) { +- ERROR("pull image %s failed", request->image); ++ ERROR("Pull image %s failed", request->image); + isulad_set_error_message("Failed to pull image %s with error: %s", request->image, g_isulad_errmsg); + ret = -1; + goto out; +@@ -197,17 +313,37 @@ int oci_do_pull_image(const im_pull_request *request, im_pull_response *response + image = storage_img_get_summary(dest_image_name); + image2 = storage_img_get_summary(request->image); + if (image == NULL || image2 == NULL) { +- ERROR("get image %s failed after pulling", request->image); ++ ERROR("Get image %s failed after pulling", request->image); + isulad_set_error_message("Failed to pull image %s with error: image not found after pulling", request->image); + ret = -1; + goto out; + } ++ arg.image = image; ++ arg.image_name = dest_image_name; ++ if (!request->is_progress_visible && stream != NULL) { ++ image_progress *progresses; + ++ progresses = util_common_calloc_s(sizeof(image_progress)); ++ if (progresses == NULL) { ++ ERROR("Out of memory. Skip progress show."); ++ goto out; ++ } ++ progresses->image = util_strdup_s(dest_image_name); ++ if (stream->write_func(stream->writer, progresses)) { ++ ERROR("Send progress data to client failed"); ++ goto out; ++ } ++ } + response->image_ref = util_strdup_s(image->id); +- ++ + out: ++ arg.should_terminal = true; ++ if (tid != 0 && pthread_join(tid, NULL) != 0) { ++ ERROR("Wait child pthread error"); ++ } + free_imagetool_image_summary(image); + free_imagetool_image_summary(image2); + free(dest_image_name); ++ progress_status_map_free(progress_status_store); + return ret; + } +diff --git a/src/daemon/modules/image/oci/oci_pull.h b/src/daemon/modules/image/oci/oci_pull.h +index 1b2eca33..79404cfe 100644 +--- a/src/daemon/modules/image/oci/oci_pull.h ++++ b/src/daemon/modules/image/oci/oci_pull.h +@@ -21,7 +21,7 @@ + extern "C" { + #endif + +-int oci_do_pull_image(const im_pull_request *request, im_pull_response *response); ++int oci_do_pull_image(const im_pull_request *request, stream_func_wrapper *stream, im_pull_response *response); + + #ifdef __cplusplus + } +diff --git a/src/daemon/modules/image/oci/progress.c b/src/daemon/modules/image/oci/progress.c +new file mode 100644 +index 00000000..110f22c0 +--- /dev/null ++++ b/src/daemon/modules/image/oci/progress.c +@@ -0,0 +1,124 @@ ++/****************************************************************************** ++ * Copyright (c) China Unicom 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: Chenwei ++ * Create: 2023-08-25 ++ * Description: provide pthread safe pull progress status map definition ++ ******************************************************************************/ ++#include "progress.h" ++#include ++#include ++ ++#include "utils.h" ++ ++/* function to get size of map */ ++size_t progress_status_map_size(progress_status_map *progress_status_map) ++{ ++ size_t ret = 0; ++ ++ if (progress_status_map == NULL) { ++ ERROR("Invalid parameter"); ++ return 0; ++ } ++ ++ if (!progress_status_map_lock(progress_status_map)) { ++ ERROR("Cannot get the progress status map size for locking failed"); ++ return 0; ++ } ++ ret = map_size(progress_status_map->map); ++ progress_status_map_unlock(progress_status_map); ++ ++ return ret; ++} ++ ++bool progress_status_map_insert(progress_status_map *progress_status_map, char *key, progress *value) ++{ ++ bool ret = false; ++ ++ if (progress_status_map == NULL || key == NULL || value == NULL) { ++ ERROR("Invalid parameter"); ++ return false; ++ } ++ ++ if (!progress_status_map_lock(progress_status_map)) { ++ ERROR("Cannot replace the progress status map item for locking failed"); ++ return false; ++ } ++ ret = map_insert(progress_status_map->map, key, value); ++ progress_status_map_unlock(progress_status_map); ++ ++ return ret; ++} ++ ++// malloc a new map by type ++progress_status_map *progress_status_map_new() ++{ ++ progress_status_map *progress_status_map = NULL; ++ progress_status_map = util_common_calloc_s(sizeof(struct progress_status_map)); ++ if (progress_status_map == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ progress_status_map->map = map_new(MAP_STR_PTR, MAP_DEFAULT_CMP_FUNC, MAP_DEFAULT_FREE_FUNC); ++ if (progress_status_map->map == NULL) { ++ free(progress_status_map); ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ if (pthread_mutex_init(&(progress_status_map->mutex), NULL) != 0) { ++ map_free(progress_status_map->map); ++ free(progress_status_map); ++ ERROR("New map failed for mutex init"); ++ return NULL; ++ } ++ return progress_status_map; ++} ++ ++/* map free */ ++void progress_status_map_free(progress_status_map *progress_status_map) ++{ ++ if (progress_status_map == NULL) { ++ return; ++ } ++ ++ pthread_mutex_destroy(&(progress_status_map->mutex)); ++ map_free(progress_status_map->map); ++ free(progress_status_map); ++} ++ ++bool progress_status_map_lock(progress_status_map *progress_status_map) ++{ ++ int ret = 0; ++ ++ if (progress_status_map == NULL) { ++ return false; ++ } ++ ++ ret = pthread_mutex_lock(&(progress_status_map->mutex)); ++ if (ret != 0) { ++ ERROR("Lock progress status map failed: %s", strerror(ret)); ++ return false; ++ } ++ return true; ++} ++ ++void progress_status_map_unlock(progress_status_map *progress_status_map) ++{ ++ int ret = 0; ++ ++ if (progress_status_map == NULL) { ++ return; ++ } ++ ++ ret = pthread_mutex_unlock(&(progress_status_map->mutex)); ++ if (ret != 0) { ++ ERROR("Unlock progress status map failed: %s", strerror(ret)); ++ } ++} +diff --git a/src/daemon/modules/image/oci/progress.h b/src/daemon/modules/image/oci/progress.h +new file mode 100644 +index 00000000..496a32f3 +--- /dev/null ++++ b/src/daemon/modules/image/oci/progress.h +@@ -0,0 +1,52 @@ ++/****************************************************************************** ++ * Copyright (c) China Unicom 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: Chenwei ++ * Create: 2023-08-25 ++ * Description: provide pthread safe pull progress status map definition ++ ******************************************************************************/ ++#ifndef DAEMON_MODULES_IMAGE_OCI_PROGRESS_STATUS_MAP_H ++#define DAEMON_MODULES_IMAGE_OCI_PROGRESS_STATUS_MAP_H ++ ++#include "map.h" ++#include ++#include ++ ++#if defined(__cplusplus) || defined(c_plusplus) ++extern "C" { ++#endif ++ ++typedef struct progress_status_map { ++ struct _map_t *map; ++ pthread_mutex_t mutex; ++} progress_status_map; ++ ++typedef struct progress { ++ int64_t dlnow; ++ int64_t dltotal; ++} progress; ++ ++bool progress_status_map_insert(progress_status_map *progress_status_map, char *key, progress *value); ++ ++progress_status_map *progress_status_map_new(); ++ ++size_t progress_status_map_size(progress_status_map *progress_status_map); ++ ++void progress_status_map_free(progress_status_map *map); ++ ++bool progress_status_map_lock(progress_status_map *progress_status_map); ++ ++void progress_status_map_unlock(progress_status_map *progress_status_map); ++ ++#if defined(__cplusplus) || defined(c_plusplus) ++} ++#endif ++ ++#endif // DAEMON_MODULES_IMAGE_OCI_PROGRESS_STATUS_MAP_H +diff --git a/src/daemon/modules/image/oci/registry/http_request.c b/src/daemon/modules/image/oci/registry/http_request.c +index a514aaef..748c9a9b 100644 +--- a/src/daemon/modules/image/oci/registry/http_request.c ++++ b/src/daemon/modules/image/oci/registry/http_request.c +@@ -15,28 +15,34 @@ + + #define _GNU_SOURCE /* See feature_test_macros(7) */ + #include "http_request.h" +-#include +-#include ++#include + #include ++#include ++#include ++#include + #include ++#include + #include ++#include + #include + #include +-#include +-#include + +-#include "isula_libutils/log.h" + #include "buffer.h" ++#include "certs.h" ++#include "err_msg.h" + #include "http.h" + #include "utils.h" + #include "utils_images.h" +-#include "certs.h" +-#include "isula_libutils/registry_token.h" +-#include "err_msg.h" ++#include "progress.h" + #include "utils_array.h" + #include "utils_base64.h" + #include "utils_string.h" + ++typedef struct progress_arg { ++ char *digest; ++ progress_status_map *map_store; ++} progress_arg; ++ + #define MIN_TOKEN_EXPIRES_IN 60 + + static int http_request_get_token(pull_descriptor *desc, challenge *c, char **output); +@@ -683,28 +689,64 @@ out: + return ret; + } + +-static int progress(void *p, double dltotal, double dlnow, double ultotal, double ulnow) ++static int xfer_inner(void *p, int64_t dltotal, int64_t dlnow, int64_t ultotal, int64_t ulnow) + { +- bool *cancel = p; +- if (*cancel) { +- // return nonzero code means abort transition ++ progress_arg *arg = (progress_arg *)p; ++ progress *progress_value = NULL; ++ ++ if (arg == NULL || arg->map_store == NULL) { ++ ERROR("Wrong progress arg"); ++ return -1; ++ } ++ // When fetch_manifest_list, there's no digest. It's not a layer pulling progress and skip it. ++ if (arg->digest == NULL) { ++ return 0; ++ } ++ ++ if (!progress_status_map_lock(arg->map_store)) { ++ ERROR("Cannot update progress status map for locking failed"); + return -1; + } ++ ++ // If the item exists, only replace the value. ++ progress_value = map_search(arg->map_store->map, arg->digest); ++ if (progress_value != NULL) { ++ progress_value->dlnow = dlnow; ++ progress_value->dltotal = dltotal; ++ progress_status_map_unlock(arg->map_store); ++ ++ return 0; ++ } ++ progress_status_map_unlock(arg->map_store); ++ ++ progress_value = util_common_calloc_s(sizeof(progress)); ++ if (progress_value == NULL) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ ++ progress_value->dlnow = dlnow; ++ progress_value->dltotal = dltotal; ++ ++ progress_status_map_insert(arg->map_store, arg->digest, progress_value); ++ + return 0; + } + ++#if (LIBCURL_VERSION_NUM >= 0x072000) + static int xfer(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) + { +- bool *cancel = p; +- if (*cancel) { +- // return nonzero code means abort transition +- return -1; +- } +- return 0; ++ return xfer_inner(p, (int64_t)dltotal, (int64_t)dlnow, (int64_t)ultotal, (int64_t)ulnow); ++} ++#else ++static int get_progress(void *p, double dltotal, double dlnow, double ultotal, double ulnow) ++{ ++ return xfer_inner(p, (int64_t)dltotal, (int64_t)dlnow, (int64_t)ultotal, (int64_t)ulnow); + } ++#endif + + int http_request_file(pull_descriptor *desc, const char *url, const char **custom_headers, char *file, +- resp_data_type type, CURLcode *errcode) ++ resp_data_type type, CURLcode *errcode, char *digest) + { + int ret = 0; + struct http_get_options *options = NULL; +@@ -730,11 +772,24 @@ int http_request_file(pull_descriptor *desc, const char *url, const char **custo + } + options->outputtype = HTTP_REQUEST_FILE; + options->output = file; +- options->show_progress = 1; +- options->progressinfo = &desc->cancel; +- options->progress_info_op = progress; +- options->xferinfo = &desc->cancel; +- options->xferinfo_op = xfer; ++ progress_arg *arg = util_common_calloc_s(sizeof(progress_arg)); ++ if (arg == NULL) { ++ ERROR("Out of memory"); ++ goto out; ++ } ++ options->show_progress = 0; ++ if (desc->progress_status_store != NULL) { ++ arg->digest = digest; ++ arg->map_store = desc->progress_status_store; ++#if (LIBCURL_VERSION_NUM >= 0x072000) ++ options->xferinfo = arg; ++ options->xferinfo_op = xfer; ++#else ++ options->progressinfo = arg; ++ options->progress_info_op = get_progress; ++#endif ++ options->show_progress = 1; ++ } + options->timeout = true; + + ret = setup_common_options(desc, options, url, custom_headers); +@@ -755,6 +810,7 @@ int http_request_file(pull_descriptor *desc, const char *url, const char **custo + out: + *errcode = options->errcode; + free_http_get_options(options); ++ free(arg); + options = NULL; + + return ret; +diff --git a/src/daemon/modules/image/oci/registry/http_request.h b/src/daemon/modules/image/oci/registry/http_request.h +index 71df37d7..ed3f7e98 100644 +--- a/src/daemon/modules/image/oci/registry/http_request.h ++++ b/src/daemon/modules/image/oci/registry/http_request.h +@@ -32,7 +32,7 @@ typedef enum { + int http_request_buf(pull_descriptor *desc, const char *url, const char **custom_headers, char **output, + resp_data_type type); + int http_request_file(pull_descriptor *desc, const char *url, const char **custom_headers, char *file, +- resp_data_type type, CURLcode *errcode); ++ resp_data_type type, CURLcode *errcode, char *digest); + + #ifdef __cplusplus + } +diff --git a/src/daemon/modules/image/oci/registry/registry.c b/src/daemon/modules/image/oci/registry/registry.c +index 4124281d..875f2df2 100644 +--- a/src/daemon/modules/image/oci/registry/registry.c ++++ b/src/daemon/modules/image/oci/registry/registry.c +@@ -1972,6 +1972,7 @@ static int prepare_pull_desc(pull_descriptor *desc, registry_pull_options *optio + } + } + ++ desc->progress_status_store = options->progress_status_store; + out: + free(image_tmp_path); + return ret; +@@ -2357,4 +2358,4 @@ void free_registry_search_options(registry_search_options *options) + free(options); + return; + } +-#endif +\ No newline at end of file ++#endif +diff --git a/src/daemon/modules/image/oci/registry/registry.h b/src/daemon/modules/image/oci/registry/registry.h +index cafb11c6..bb2af348 100644 +--- a/src/daemon/modules/image/oci/registry/registry.h ++++ b/src/daemon/modules/image/oci/registry/registry.h +@@ -16,6 +16,7 @@ + #define DAEMON_MODULES_IMAGE_OCI_REGISTRY_REGISTRY_H + + #include ++#include "progress.h" + + #ifdef ENABLE_IMAGE_SEARCH + #include +@@ -36,6 +37,7 @@ typedef struct { + registry_auth auth; + bool skip_tls_verify; + bool insecure_registry; ++ progress_status_map *progress_status_store; // Don't free it. It's freed at oci_pull.c. + } registry_pull_options; + + typedef struct { +diff --git a/src/daemon/modules/image/oci/registry/registry_apiv2.c b/src/daemon/modules/image/oci/registry/registry_apiv2.c +index db4d311e..2859de7c 100644 +--- a/src/daemon/modules/image/oci/registry/registry_apiv2.c ++++ b/src/daemon/modules/image/oci/registry/registry_apiv2.c +@@ -409,7 +409,7 @@ out: + } + + static int registry_request(pull_descriptor *desc, char *path, char **custom_headers, char *file, char **output_buffer, +- resp_data_type type, CURLcode *errcode) ++ resp_data_type type, CURLcode *errcode, char *digest) + { + int ret = 0; + int sret = 0; +@@ -457,7 +457,7 @@ static int registry_request(pull_descriptor *desc, char *path, char **custom_hea + } + DEBUG("resp=%s", *output_buffer); + } else { +- ret = http_request_file(desc, url, (const char **)headers, file, type, errcode); ++ ret = http_request_file(desc, url, (const char **)headers, file, type, errcode, digest); + if (ret != 0) { + ERROR("http request file failed, url: %s", url); + goto out; +@@ -679,7 +679,7 @@ static int fetch_manifest_list(pull_descriptor *desc, char *file, char **content + + while (retry_times > 0) { + retry_times--; +- ret = registry_request(desc, path, custom_headers, file, NULL, HEAD_BODY, &errcode); ++ ret = registry_request(desc, path, custom_headers, file, NULL, HEAD_BODY, &errcode, NULL); + if (ret != 0) { + if (retry_times > 0 && !desc->cancel) { + continue; +@@ -762,7 +762,7 @@ static int fetch_data(pull_descriptor *desc, char *path, char *file, char *conte + + while (retry_times > 0) { + retry_times--; +- ret = registry_request(desc, path, custom_headers, file, NULL, type, &errcode); ++ ret = registry_request(desc, path, custom_headers, file, NULL, type, &errcode, digest); + if (ret != 0) { + if (errcode == CURLE_RANGE_ERROR) { + forbid_resume = true; +@@ -1211,7 +1211,7 @@ int login_to_registry(pull_descriptor *desc) + goto out; + } + +- ret = registry_request(desc, path, NULL, NULL, &resp_buffer, HEAD_BODY, &errcode); ++ ret = registry_request(desc, path, NULL, NULL, &resp_buffer, HEAD_BODY, &errcode, NULL); + if (ret != 0) { + ERROR("registry: Get %s failed, resp: %s", path, resp_buffer); + isulad_try_set_error_message("login to registry for %s failed", desc->host); +@@ -1235,4 +1235,4 @@ out: + resp_buffer = NULL; + + return ret; +-} +\ No newline at end of file ++} +diff --git a/src/daemon/modules/image/oci/registry_type.h b/src/daemon/modules/image/oci/registry_type.h +index f232f227..8ddfcfea 100644 +--- a/src/daemon/modules/image/oci/registry_type.h ++++ b/src/daemon/modules/image/oci/registry_type.h +@@ -20,6 +20,7 @@ + #include + #include + ++#include "progress.h" + #include "utils_timestamp.h" + + // 8 is enough for challenge, usually only one challenge is provided. +@@ -134,6 +135,8 @@ typedef struct { + char *search_name; + uint32_t limit; + #endif ++ ++ progress_status_map *progress_status_store; // Don't free it. It's freed at other place. + } pull_descriptor; + + void free_challenge(challenge *c); +diff --git a/src/utils/CMakeLists.txt b/src/utils/CMakeLists.txt +index 6933caf5..42814fd6 100644 +--- a/src/utils/CMakeLists.txt ++++ b/src/utils/CMakeLists.txt +@@ -7,6 +7,7 @@ add_subdirectory(sha256) + add_subdirectory(tar) + add_subdirectory(http) + add_subdirectory(buffer) ++add_subdirectory(progress) + + set(local_utils_srcs + ${utils_top_srcs} +@@ -15,6 +16,7 @@ set(local_utils_srcs + ${CUTILS_SRCS} + ${CONSOLE_SRCS} + ${BUFFER_SRCS} ++ ${PROGRESS_SRCS} + ) + + set(local_utils_incs +@@ -24,6 +26,7 @@ set(local_utils_incs + ${CUTILS_INCS} + ${CONSOLE_INCS} + ${BUFFER_INCS} ++ ${PROGRESS_INCS} + ) + + if (GRPC_CONNECTOR) +diff --git a/src/utils/http/http.h b/src/utils/http/http.h +index 02d56ba8..585afdf1 100644 +--- a/src/utils/http/http.h ++++ b/src/utils/http/http.h +@@ -23,12 +23,15 @@ + extern "C" { + #endif + +-typedef int(*progress_info_func)(void *p, +- double dltotal, double dlnow, +- double ultotal, double ulnow); ++#if (LIBCURL_VERSION_NUM >= 0x072000) + typedef int(*xferinfo_func)(void *p, + curl_off_t dltotal, curl_off_t dlnow, + curl_off_t ultotal, curl_off_t ulnow); ++#else ++typedef int(*progress_info_func)(void *p, ++ double dltotal, double dlnow, ++ double ultotal, double ulnow); ++#endif + + struct http_get_options { + unsigned with_head : 1, /* if set, means write output with response HEADER */ +@@ -79,11 +82,13 @@ struct http_get_options { + + bool timeout; + +- void *progressinfo; +- progress_info_func progress_info_op; +- ++#if (LIBCURL_VERSION_NUM >= 0x072000) + void *xferinfo; + xferinfo_func xferinfo_op; ++#else ++ void *progressinfo; ++ progress_info_func progress_info_op; ++#endif + }; + + #define HTTP_RES_OK 0 +diff --git a/src/utils/progress/CMakeLists.txt b/src/utils/progress/CMakeLists.txt +new file mode 100644 +index 00000000..d06cca33 +--- /dev/null ++++ b/src/utils/progress/CMakeLists.txt +@@ -0,0 +1,13 @@ ++# get current directory sources files ++aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR} local_progress_srcs) ++ ++set(PROGRESS_SRCS ++ ${local_progress_srcs} ++ PARENT_SCOPE ++ ) ++ ++set(PROGRESS_INCS ++ ${CMAKE_CURRENT_SOURCE_DIR} ++ PARENT_SCOPE ++ ) ++ +diff --git a/src/utils/progress/show.c b/src/utils/progress/show.c +new file mode 100644 +index 00000000..fbefe344 +--- /dev/null ++++ b/src/utils/progress/show.c +@@ -0,0 +1,64 @@ ++/****************************************************************************** ++ * Copyright (c) China Unicom 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: Chenwei ++ * Create: 2023-08-25 ++ * Description: print progress ++ ******************************************************************************/ ++ ++#include "show.h" ++#include ++#include ++#include ++#include ++ ++void move_to_row(int row) ++{ ++ printf("\033[%d;1H", row); ++ fflush(stdout); ++} ++ ++void move_cursor_up(int rows) ++{ ++ printf("\033[%dA", rows); // ANSI escape code to move cursor up 'rows' rows ++} ++ ++void clear_row(int row) ++{ ++ move_to_row(row); ++ printf("\033[2K"); ++ fflush(stdout); ++} ++ ++void clear_lines_below() ++{ ++ printf("\x1b[J"); // ANSI escape code to clear from cursor to end of screen ++ fflush(stdout); ++} ++ ++int get_current_row() ++{ ++ struct termios term; ++ if (tcgetattr(STDOUT_FILENO, &term) == -1) { ++ perror("tcgetattr"); ++ return -1; ++ } ++ return term.c_cc[VERASE]; ++} ++ ++int get_terminal_width() ++{ ++ struct winsize ws; ++ if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) == -1) { ++ perror("ioctl"); ++ return -1; // Error ++ } ++ return ws.ws_col; ++} +diff --git a/src/utils/progress/show.h b/src/utils/progress/show.h +new file mode 100644 +index 00000000..c1f71d86 +--- /dev/null ++++ b/src/utils/progress/show.h +@@ -0,0 +1,34 @@ ++/****************************************************************************** ++ * Copyright (c) China Unicom 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: Chenwei ++ * Create: 2023-08-25 ++ * Description: print progress ++ ******************************************************************************/ ++ ++#ifndef UTILS_SHOW_H ++#define UTILS_SHOW_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++void move_to_row(int row); ++void move_cursor_up(int lines); ++void clear_row(int row); ++void clear_lines_below(); ++int get_current_row(); ++int get_terminal_width(); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +diff --git a/test/cutils/CMakeLists.txt b/test/cutils/CMakeLists.txt +index 10a10db9..9e681cc9 100644 +--- a/test/cutils/CMakeLists.txt ++++ b/test/cutils/CMakeLists.txt +@@ -34,3 +34,4 @@ add_subdirectory(utils_utils) + add_subdirectory(utils_verify) + add_subdirectory(utils_network) + add_subdirectory(utils_transform) ++add_subdirectory(map) +diff --git a/test/image/oci/registry/CMakeLists.txt b/test/image/oci/registry/CMakeLists.txt +index f9ba056e..77a7907e 100644 +--- a/test/image/oci/registry/CMakeLists.txt ++++ b/test/image/oci/registry/CMakeLists.txt +@@ -18,6 +18,7 @@ add_executable(${EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/cutils/map/rb_tree.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/cutils/utils_timestamp.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/modules/image/oci/utils_images.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/modules/image/oci/progress.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/daemon/common/err_msg.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/http/parser.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../src/utils/buffer/buffer.c +diff --git a/test/image/oci/registry/registry_ut.cc b/test/image/oci/registry/registry_ut.cc +index f4f8a763..3cb3e371 100644 +--- a/test/image/oci/registry/registry_ut.cc ++++ b/test/image/oci/registry/registry_ut.cc +@@ -214,21 +214,7 @@ int invokeHttpRequestV2(const char *url, struct http_get_options *options, long + } else if (util_has_prefix(url, "http://hub-mirror.c.163.com/v2/library/busybox/blobs/sha256:c7c37e47")) { + file = data_path + "config"; + if (count == COUNT_TEST_CANCEL) { +- bool *cancel = (bool *)options->progressinfo; +- while (!(*cancel)) { +- sleep(1); // schedule out to let cancel variable set to be true +- } +- if (options->progress_info_op(options->progressinfo, 0, 0, 0, 0) != 0) { +- return -1; +- } +- +- cancel = (bool *)options->xferinfo; +- while (!(*cancel)) { +- sleep(1); // schedule out to let cancel variable set to be true +- } +- if (options->xferinfo_op(options->xferinfo, 0, 0, 0, 0) != 0) { +- return -1; +- } ++ return 0; + } + } else if (util_has_prefix(url, "http://hub-mirror.c.163.com/v2/library/busybox/blobs/sha256:91f30d77")) { + if (retry) { +-- +2.42.0 + diff --git a/0025-2084-image-pull.patch b/0025-2084-image-pull.patch new file mode 100644 index 0000000..0fe36f1 --- /dev/null +++ b/0025-2084-image-pull.patch @@ -0,0 +1,84 @@ +From 79384f7b0ac7319120d1f677323c43069742a354 Mon Sep 17 00:00:00 2001 +From: sailorvii +Date: Wed, 22 Nov 2023 01:22:42 +0000 +Subject: [PATCH 25/64] =?UTF-8?q?!2084=20=E5=A2=9E=E5=8A=A0image=20pull=20?= + =?UTF-8?q?=E6=97=B6=E8=BF=9B=E5=BA=A6=E6=9D=A1=E6=98=BE=E7=A4=BA=E7=9A=84?= + =?UTF-8?q?=E8=AE=BE=E8=AE=A1=20*=20Refine=20document=20by=20the=20impleme?= + =?UTF-8?q?ntation.=20*=20Refine=20a=20word.=20*=20Add=20progress=20bard?= + =?UTF-8?q?=20proposal.?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + docs/design/detailed/Misc/progressBar.md | 58 ++++++++++++++++++++++++ + 1 file changed, 58 insertions(+) + create mode 100644 docs/design/detailed/Misc/progressBar.md + +diff --git a/docs/design/detailed/Misc/progressBar.md b/docs/design/detailed/Misc/progressBar.md +new file mode 100644 +index 00000000..3cf733a6 +--- /dev/null ++++ b/docs/design/detailed/Misc/progressBar.md +@@ -0,0 +1,58 @@ ++# 方案目标 ++在Image pull过程中,显示多个layer下载的进度。 ++ ++之前的grpc pull和cri pull共用了接口,需要新增grpc pull接口,该接口类型为stream,带progress status。 ++重写函数oci_do_pull_image,底层函数pull_image复用。 ++在结构体registry_pull_options增加map。 ++ ++# 限制 ++1. 每一个connection只做一件事,否则progress store会混乱。 ++2. 这个功能只为grpc 连接服务。 ++ ++# 总体设计 ++## 主要功能模块 ++### Progress status store ++每次pull命令或者行为为一个connection。每个image会按照layer来下载。所以我们建立了一个status map。 map的key为Layer ID,内容结构体定义如下: ++ ++``` ++struct progress_status { ++ // Layer ID ++ char ID[13]; ++ ++ // total is the end value describing when we made 100% progress for an operation. Unit is Byte. ++ int64 total; ++ ++ // current is the current value for the operation. Unit is Byte. ++ int64 current; ++} ++``` ++ ++#### API ++``` ++progress_status_map *progress_status_map_new(); ++ ++bool progress_status_map_insert(progress_status_map *progress_status_map, char *key, progress *value); ++ ++``` ++ ++### Client Progress 显示 ++在client每次读到消息时,获取当前窗口宽度(termios.h: tcgetattr),如果宽度小于110字符,则压缩显示(已下载/全部字节),如果不是,则显示进度条。 ++当第一次收到时,计算需要显示的任务数task number,每个任务显示一行。 ++当更新状态时,将光标回退task number行,清除该行,打印完一行,将光标移到下一行清除该行并打印新的进度,重复上述步骤直至所有任务打印完成。 ++ ++## 主要流程 ++### 下载任务获取下载状态 ++在结构体pull_descriptor新增*progress_status_store, 传递write_progress_status的map *。 ++ ++在http_request中,修改原来的桩函数xfer,这个函数将实时采集curl pull的状态,如当前下载的字节数,总的字节数。 ++ ++ ++### server获取下载状态并传递给client ++新增函数int ImagesServiceImpl::PullImage,函数Response参数为stream,每隔100ms读取progress status map并序列化为json message,写入response stream。 ++``` ++Status ImagesServiceImpl::PullImage(ServerContext *context, const PullImageRequest *request, ++ ServerWriter *writer) ++``` ++ ++### client收取状态并显示 ++修改原来的grpc_images_client中ImagesPull函数。阻塞式读取response stream, 流不为空则一直读取并打印显示每个progress status。 +-- +2.42.0 + diff --git a/0026-CI-add-ncurse-for-ubuntu-and-centos.patch b/0026-CI-add-ncurse-for-ubuntu-and-centos.patch new file mode 100644 index 0000000..de75868 --- /dev/null +++ b/0026-CI-add-ncurse-for-ubuntu-and-centos.patch @@ -0,0 +1,39 @@ +From c87ecc7f26a0a0034a8bf49691f572fe1d4fed29 Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Wed, 22 Nov 2023 15:00:24 +0800 +Subject: [PATCH 26/64] [CI] add ncurse for ubuntu and centos + +Signed-off-by: haozi007 +--- + CI/dockerfiles/Dockerfile-centos | 2 ++ + CI/dockerfiles/Dockerfile-ubuntu | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/CI/dockerfiles/Dockerfile-centos b/CI/dockerfiles/Dockerfile-centos +index 7250b7bd..1d76b4ec 100644 +--- a/CI/dockerfiles/Dockerfile-centos ++++ b/CI/dockerfiles/Dockerfile-centos +@@ -299,5 +299,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 ++ + VOLUME [ "/sys/fs/cgroup" ] + CMD ["/usr/sbin/init"] +diff --git a/CI/dockerfiles/Dockerfile-ubuntu b/CI/dockerfiles/Dockerfile-ubuntu +index f84ae0a7..2441a7ce 100644 +--- a/CI/dockerfiles/Dockerfile-ubuntu ++++ b/CI/dockerfiles/Dockerfile-ubuntu +@@ -84,7 +84,7 @@ RUN apt update -y && apt upgrade -y && \ + patch \ + tcpdump + +-RUN apt autoremove -y ++RUN apt install -y libncurses-dev && apt autoremove -y + RUN pip3 install meson ninja + + RUN echo "export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH" >> /etc/bashrc && \ +-- +2.42.0 + diff --git a/0027-improve-code-of-pull-progress.patch b/0027-improve-code-of-pull-progress.patch new file mode 100644 index 0000000..86b4eca --- /dev/null +++ b/0027-improve-code-of-pull-progress.patch @@ -0,0 +1,631 @@ +From 78304f7ad584517e02125c928e976f34aaf859f8 Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Wed, 22 Nov 2023 15:00:43 +0800 +Subject: [PATCH 27/64] improve code of pull progress + +Signed-off-by: haozi007 +--- + src/client/connect/CMakeLists.txt | 7 +- + src/client/connect/grpc/grpc_images_client.cc | 48 ++---- + .../connect/grpc/grpc_volumes_client.cc | 1 - + src/daemon/common/events_format.h | 2 + + .../v1/v1_cri_image_manager_service_impl.cc | 2 - + .../v1alpha/cri_image_manager_service_impl.cc | 2 - + src/daemon/executor/image_cb/image_cb.c | 2 + + src/daemon/modules/api/event_type.h | 4 +- + src/daemon/modules/events/collector.c | 4 +- + src/daemon/modules/image/image.c | 2 +- + src/daemon/modules/image/oci/oci_pull.c | 146 ++++++++++-------- + src/daemon/modules/image/oci/progress.c | 28 +++- + src/daemon/modules/image/oci/progress.h | 6 +- + .../modules/image/oci/registry/http_request.c | 28 +--- + .../oci/storage/image_store/image_store.c | 2 +- + .../graphdriver/overlay2/driver_overlay2.c | 2 +- + .../modules/image/oci/storage/storage.c | 5 +- + 17 files changed, 137 insertions(+), 154 deletions(-) + +diff --git a/src/client/connect/CMakeLists.txt b/src/client/connect/CMakeLists.txt +index 00ba2f68..d4ce6c9c 100644 +--- a/src/client/connect/CMakeLists.txt ++++ b/src/client/connect/CMakeLists.txt +@@ -12,10 +12,7 @@ if (GRPC_CONNECTOR) + aux_source_directory(${CMAKE_BINARY_DIR}/grpc/src/api/services/containers CONNECT_API_CONTAINERS) + aux_source_directory(${CMAKE_BINARY_DIR}/grpc/src/api/services/images CONNECT_API_IMAGES) + aux_source_directory(${CMAKE_BINARY_DIR}/grpc/src/api/services/volumes CONNECT_API_VOLUMES) +- # TODO: current isula pull use CRI pullImage API, we should remove this dependence +- aux_source_directory(${CMAKE_BINARY_DIR}/grpc/src/api/services/cri CONNECT_API_CRI) +- aux_source_directory(${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/v1alpha CONNECT_API_CRI_ALPHAS) +- set(CONNECT_API ${CONNECT_API_VOLUMES} ${CONNECT_API_CONTAINERS} ${CONNECT_API_IMAGES} ${CONNECT_API_CRI_ALPHAS} ${CONNECT_API_CRI}) ++ set(CONNECT_API ${CONNECT_API_VOLUMES} ${CONNECT_API_CONTAINERS} ${CONNECT_API_IMAGES}) + list(APPEND local_client_connect_srcs ${CONNECT_API}) + + list(APPEND local_client_connect_incs ${CMAKE_CURRENT_SOURCE_DIR}/grpc) +@@ -23,8 +20,6 @@ if (GRPC_CONNECTOR) + ${CMAKE_BINARY_DIR}/grpc/src/api/services/volumes + ${CMAKE_BINARY_DIR}/grpc/src/api/services/containers + ${CMAKE_BINARY_DIR}/grpc/src/api/services/images +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri +- ${CMAKE_BINARY_DIR}/grpc/src/api/services/cri/v1alpha + ) + + if(ENABLE_NATIVE_NETWORK) +diff --git a/src/client/connect/grpc/grpc_images_client.cc b/src/client/connect/grpc/grpc_images_client.cc +index 7a283e8c..7fd36cc1 100644 +--- a/src/client/connect/grpc/grpc_images_client.cc ++++ b/src/client/connect/grpc/grpc_images_client.cc +@@ -390,50 +390,20 @@ public: + return 0; + } + +- auto run(const struct isula_pull_request *request, struct isula_pull_response *response) -> int override +- { +- ClientContext context; +- PullImageRequest grequest; +- +-#ifdef ENABLE_GRPC_REMOTE_CONNECT +-#ifdef OPENSSL_VERIFY +- // Set common name from cert.perm +- char common_name_value[ClientBaseConstants::COMMON_NAME_LEN] = { 0 }; +- int ret = get_common_name_from_tls_cert(m_certFile.c_str(), common_name_value, +- ClientBaseConstants::COMMON_NAME_LEN); +- if (ret != 0) { +- ERROR("Failed to get common name in: %s", m_certFile.c_str()); +- return -1; +- } +- context.AddMetadata("username", std::string(common_name_value, strlen(common_name_value))); +- context.AddMetadata("tls_mode", m_tlsMode); +-#endif +-#endif +- if (request_to_grpc(request, &grequest) != 0) { +- ERROR("Failed to transform pull request to grpc"); +- response->server_errono = ISULAD_ERR_INPUT; +- return -1; +- } +- +- auto reader = stub_->PullImage(&context, grequest); ++ auto grpc_call(ClientContext *context, const PullImageRequest &req, PullImageResponse *reply) -> Status override ++ { ++ auto reader = stub_->PullImage(context, req); + +- PullImageResponse gresponse; +- if (grequest.is_progress_visible()) { +- while (reader->Read(&gresponse)) { +- output_progress(gresponse); ++ if (req.is_progress_visible()) { ++ while (reader->Read(reply)) { ++ output_progress(*reply); + } + } else { +- reader->Read(&gresponse); ++ reader->Read(reply); + WARN("The terminal may not support ANSI Escape code. Display is skipped"); + } +- Status status = reader->Finish(); +- if (!status.ok()) { +- ERROR("Error code: %d: %s", status.error_code(), status.error_message().c_str()); +- unpackStatus(status, response); +- return -1; +- } +- response->image_ref = util_strdup_s(gresponse.image_ref().c_str()); +- return 0; ++ ++ return reader->Finish(); + } + + private: +diff --git a/src/client/connect/grpc/grpc_volumes_client.cc b/src/client/connect/grpc/grpc_volumes_client.cc +index 32b83a9e..5fe8ed5e 100644 +--- a/src/client/connect/grpc/grpc_volumes_client.cc ++++ b/src/client/connect/grpc/grpc_volumes_client.cc +@@ -16,7 +16,6 @@ + + #include + +-#include "api.grpc.pb.h" + #include "client_base.h" + #include "volumes.grpc.pb.h" + #include "utils.h" +diff --git a/src/daemon/common/events_format.h b/src/daemon/common/events_format.h +index 7e97b2c5..6b8fcfd5 100644 +--- a/src/daemon/common/events_format.h ++++ b/src/daemon/common/events_format.h +@@ -64,6 +64,8 @@ typedef enum { + EVENTS_TYPE_IMAGE_PULL, + EVENTS_TYPE_IMAGE_LOGIN, + EVENTS_TYPE_IMAGE_LOGOUT, ++ EVENTS_TYPE_IMAGE_IMPORT, ++ EVENTS_TYPE_IMAGE_TAG, + EVENTS_TYPE_IMAGE_MAX_STATE + } image_events_type_t; + +diff --git a/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.cc b/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.cc +index b9cbf24c..066eed5e 100644 +--- a/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.cc ++++ b/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.cc +@@ -25,7 +25,6 @@ + + #include "v1_cri_helpers.h" + #include "err_msg.h" +-#include "events_sender_api.h" + #include "isula_libutils/log.h" + #include "service_image_api.h" + #include "utils.h" +@@ -277,7 +276,6 @@ auto ImageManagerServiceImpl::PullImage(const runtime::v1::ImageSpec &image, + if (response->image_ref != nullptr) { + out_str = response->image_ref; + } +- (void)isulad_monitor_send_image_event(request->image, IM_PULL); + + cleanup: + DAEMON_CLEAR_ERRMSG(); +diff --git a/src/daemon/entry/cri/v1alpha/cri_image_manager_service_impl.cc b/src/daemon/entry/cri/v1alpha/cri_image_manager_service_impl.cc +index 0b36f007..9015df26 100644 +--- a/src/daemon/entry/cri/v1alpha/cri_image_manager_service_impl.cc ++++ b/src/daemon/entry/cri/v1alpha/cri_image_manager_service_impl.cc +@@ -25,7 +25,6 @@ + + #include "cri_helpers.h" + #include "err_msg.h" +-#include "events_sender_api.h" + #include "isula_libutils/log.h" + #include "service_image_api.h" + #include "utils.h" +@@ -277,7 +276,6 @@ auto ImageManagerServiceImpl::PullImage(const runtime::v1alpha2::ImageSpec &imag + if (response->image_ref != nullptr) { + out_str = response->image_ref; + } +- (void)isulad_monitor_send_image_event(request->image, IM_PULL); + + cleanup: + DAEMON_CLEAR_ERRMSG(); +diff --git a/src/daemon/executor/image_cb/image_cb.c b/src/daemon/executor/image_cb/image_cb.c +index 317cb0a8..60899f2b 100644 +--- a/src/daemon/executor/image_cb/image_cb.c ++++ b/src/daemon/executor/image_cb/image_cb.c +@@ -519,6 +519,7 @@ static int image_tag_cb(const image_tag_image_request *request, image_tag_image_ + } + + EVENT("Image Event: {Object: %s, Type: Tagged}", request->src_name); ++ (void)isulad_monitor_send_image_event(request->src_name, IM_TAG); + + out: + if (*response != NULL) { +@@ -997,6 +998,7 @@ static int image_pull_cb(const image_pull_image_request *request, stream_func_wr + } + + EVENT("Image Event: {Object: %s, Type: Pulled}", request->image_name); ++ (void)isulad_monitor_send_image_event(request->image_name, IM_PULL); + + out: + (*response)->cc = cc; +diff --git a/src/daemon/modules/api/event_type.h b/src/daemon/modules/api/event_type.h +index c3c7951b..4f2aaf28 100644 +--- a/src/daemon/modules/api/event_type.h ++++ b/src/daemon/modules/api/event_type.h +@@ -54,7 +54,9 @@ typedef enum { + MAX_STATE, + } runtime_state_t; + +-typedef enum { IM_LOAD, IM_REMOVE, IM_PULL, IM_LOGIN, IM_LOGOUT, IM_IMPORT } image_state_t; ++// relate to g_isulad_image_event_strtype and image_events_type_t ++// we should keep them consistent ++typedef enum { IM_LOAD, IM_REMOVE, IM_PULL, IM_LOGIN, IM_LOGOUT, IM_IMPORT, IM_TAG } image_state_t; + + typedef enum { CONTAINER_EVENT, IMAGE_EVENT } msg_event_type_t; + typedef enum { MONITORD_MSG_STATE, MONITORD_MSG_PRIORITY, MONITORD_MSG_EXIT_CODE } msg_type_t; +diff --git a/src/daemon/modules/events/collector.c b/src/daemon/modules/events/collector.c +index b82ede81..36aa9299 100644 +--- a/src/daemon/modules/events/collector.c ++++ b/src/daemon/modules/events/collector.c +@@ -157,11 +157,11 @@ static const char *isulad_event_sta2str(container_events_type_t sta) + return g_isulad_event_strtype[sta]; + } + +-static const char * const g_isulad_image_event_strtype[] = { "load", "remove", "pull", "login", "logout" }; ++static const char * const g_isulad_image_event_strtype[] = { "load", "remove", "pull", "login", "logout", "import", "tag" }; + + static const char *isulad_image_event_sta2str(image_events_type_t sta) + { +- if (sta > EVENTS_TYPE_IMAGE_LOGOUT) { ++ if (sta >= EVENTS_TYPE_IMAGE_MAX_STATE) { + return NULL; + } + +diff --git a/src/daemon/modules/image/image.c b/src/daemon/modules/image/image.c +index 8d7e2c1a..4a1950fe 100644 +--- a/src/daemon/modules/image/image.c ++++ b/src/daemon/modules/image/image.c +@@ -784,7 +784,7 @@ int im_merge_image_config(const char *image_type, const char *image_name, contai + int ret = 0; + struct bim *bim = NULL; + +- // there is no need to judge the image name as empty, ++ // there is no need to judge the image name as empty, + // because the image name of external type allows it to be empty. + if (container_spec == NULL || image_type == NULL) { + ERROR("Invalid input arguments"); +diff --git a/src/daemon/modules/image/oci/oci_pull.c b/src/daemon/modules/image/oci/oci_pull.c +index 2706af91..9ad875a5 100644 +--- a/src/daemon/modules/image/oci/oci_pull.c ++++ b/src/daemon/modules/image/oci/oci_pull.c +@@ -75,7 +75,8 @@ out: + return ret; + } + +-static void update_option_insecure_registry(registry_pull_options *options, char **insecure_registries, const char *host) ++static void update_option_insecure_registry(registry_pull_options *options, char **insecure_registries, ++ const char *host) + { + char **registry = NULL; + +@@ -188,83 +189,95 @@ typedef struct status_arg { + stream_func_wrapper *stream; + } status_arg; + ++static int do_get_progress_from_store(progress_status_map *status_store, image_progress *result) ++{ ++ int i = 0; ++ size_t progress_size = progress_status_map_size(status_store); ++ ++ result->progresses = util_smart_calloc_s(sizeof(image_progress_progresses_element *), progress_size); ++ if (result->progresses == NULL) { ++ ERROR("Out of memory"); ++ return -1; ++ } ++ ++ if (!progress_status_map_lock(status_store)) { ++ WARN("Cannot itorate progress status map for locking failed"); ++ // ignore lock error, retry lock after delay. ++ return 0; ++ } ++ ++ map_itor *itor = map_itor_new(status_store->map); ++ for (i = 0; map_itor_valid(itor) && i < progress_size; map_itor_next(itor), i++) { ++ void *id = map_itor_key(itor); ++ const progress *value = (progress *)map_itor_value(itor); ++ const int ID_LEN = 12; // The last 12 charactos of image digest. ++ ++ result->progresses[i] = util_common_calloc_s(sizeof(image_progress_progresses_element)); ++ if (result->progresses[i] == NULL) { ++ // ignore error, return got progress data ++ WARN("Out of memory"); ++ break; ++ } ++ result->progresses[i]->id = util_strdup_s((char *)id + strlen((char *)id) - ID_LEN); ++ result->progresses[i]->total = value->dltotal; ++ result->progresses[i]->current = value->dlnow; ++ result->progresses_len++; ++ } ++ map_itor_free(itor); ++ progress_status_map_unlock(status_store); ++ ++ return 0; ++} ++ + void *get_progress_status(void *arg) + { + status_arg *status = (status_arg *)arg; +- const int delay = 100; // Sleep for 100 milliseconds +- bool write_ok = false; ++ ++ prctl(PR_SET_NAME, "PullProgress"); + + if (status == NULL || status->status_store == NULL || status->stream == NULL) { + ERROR("Get progress status condition error"); + return NULL; + } + +- for (;;) { +- int i = 0; +- +- usleep(delay * 1000); // Sleep for 100 milliseconds ++ while (!status->should_terminal || status->image != NULL) { ++ bool write_ok = false; ++ image_progress *iprogresses = NULL; + +- if (status->should_terminal && status->image == NULL) { ++ // Step 1: delay 100ms, wait progress update ++ util_usleep_nointerupt(100 * 1000); ++ ++ // Step 2: check client whether is canceled? ++ if (status->stream->is_cancelled(status->stream->context)) { ++ WARN("pull stream is cancelled"); + break; + } +- +- image_progress *progresses; +- size_t progress_size = progress_status_map_size(status->status_store); + +- progresses = util_common_calloc_s(sizeof(image_progress)); +- if (progresses == NULL) { +- ERROR("Out of memory. Skip progress show."); +- break; ++ iprogresses = util_common_calloc_s(sizeof(image_progress)); ++ if (iprogresses == NULL) { ++ ERROR("Out of memory"); ++ break; + } +- +- progresses->progresses = util_smart_calloc_s(sizeof(image_progress_progresses_element *), progress_size); +- if (progresses->progresses == NULL) { +- ERROR("Out of memory. Skip progress show."); +- goto roundend; ++ // Step 3: get progress of pull from progress status store ++ if (do_get_progress_from_store(status->status_store, iprogresses) != 0) { ++ free_image_progress(iprogresses); ++ break; + } ++ ++ // Step 4: check main thread whether is finished, and setted pulled image info + if (status->image != NULL) { +- progresses->image = util_strdup_s(status->image_name); ++ iprogresses->image = util_strdup_s(status->image_name); + status->image = NULL; + } + +- if (!progress_status_map_lock(status->status_store)) { +- ERROR("Cannot itorate progress status map for locking failed"); +- goto roundend; +- } +- map_itor *itor = map_itor_new(status->status_store->map); +- for (i = 0; map_itor_valid(itor) && i < progress_size; map_itor_next(itor), i++) { +- void *id = map_itor_key(itor); +- const progress *value = (progress *)map_itor_value(itor); +- const int ID_LEN = 12; // The last 12 charactos of image digest. +- +- progresses->progresses[i] = util_common_calloc_s(sizeof(image_progress_progresses_element)); +- if (progresses->progresses[i] == NULL) { +- WARN("Out of memory. Skip progress show."); +- map_itor_free(itor); +- progress_status_map_unlock(status->status_store); +- goto roundend; +- } +- progresses->progresses[i]->id = util_strdup_s((char *)id + strlen((char *)id) - ID_LEN); +- progresses->progresses[i]->total = value->dltotal; +- progresses->progresses[i]->current = value->dlnow; +- progresses->progresses_len++; ++ // Step 5: send got progress of pull to client ++ write_ok = status->stream->write_func(status->stream->writer, iprogresses); ++ if (!write_ok) { ++ WARN("Send progress data to client failed, just ignore and retry it"); + } +- map_itor_free(itor); +- progress_status_map_unlock(status->status_store); +- +- /* send to client */ +- write_ok = status->stream->write_func(status->stream->writer, progresses); +- if (write_ok) { +- goto roundend; +- } +- if (status->stream->is_cancelled(status->stream->context)) { +- ERROR("pull stream is cancelled"); +- goto roundend; +- } +- ERROR("Send progress data to client failed"); +-roundend: +- free_image_progress(progresses); ++ free_image_progress(iprogresses); + } ++ + return NULL; + } + +@@ -286,7 +299,7 @@ int oci_do_pull_image(const im_pull_request *request, stream_func_wrapper *strea + if (request->is_progress_visible && stream != NULL) { + progress_status_store = progress_status_map_new(); + if (progress_status_store == NULL) { +- ERROR("Out of memory and will not show the pull progress"); ++ ERROR("Out of memory"); + isulad_set_error_message("Failed to pull image %s with error: out of memory", request->image); + ret = -1; + goto out; +@@ -321,21 +334,28 @@ int oci_do_pull_image(const im_pull_request *request, stream_func_wrapper *strea + arg.image = image; + arg.image_name = dest_image_name; + if (!request->is_progress_visible && stream != NULL) { +- image_progress *progresses; ++ image_progress *progresses = NULL; ++ bool nret = false; + + progresses = util_common_calloc_s(sizeof(image_progress)); + if (progresses == NULL) { +- ERROR("Out of memory. Skip progress show."); +- goto out; ++ ERROR("Out of memory"); ++ isulad_set_error_message("Failed to pull image %s with error: out of memory", request->image); ++ ret = -1; ++ goto out; + } + progresses->image = util_strdup_s(dest_image_name); +- if (stream->write_func(stream->writer, progresses)) { ++ nret = stream->write_func(stream->writer, progresses); ++ free_image_progress(progresses); ++ if (!nret) { + ERROR("Send progress data to client failed"); ++ isulad_set_error_message("Failed to pull image %s with error: send progress data to client failed", request->image); ++ ret = -1; + goto out; + } + } + response->image_ref = util_strdup_s(image->id); +- ++ + out: + arg.should_terminal = true; + if (tid != 0 && pthread_join(tid, NULL) != 0) { +diff --git a/src/daemon/modules/image/oci/progress.c b/src/daemon/modules/image/oci/progress.c +index 110f22c0..7d0c10a4 100644 +--- a/src/daemon/modules/image/oci/progress.c ++++ b/src/daemon/modules/image/oci/progress.c +@@ -34,15 +34,16 @@ size_t progress_status_map_size(progress_status_map *progress_status_map) + } + ret = map_size(progress_status_map->map); + progress_status_map_unlock(progress_status_map); +- ++ + return ret; + } + +-bool progress_status_map_insert(progress_status_map *progress_status_map, char *key, progress *value) ++bool progress_status_map_udpate(progress_status_map *progress_status_map, char *key, int64_t current, int64_t total) + { + bool ret = false; ++ progress *pval = NULL; + +- if (progress_status_map == NULL || key == NULL || value == NULL) { ++ if (progress_status_map == NULL || key == NULL) { + ERROR("Invalid parameter"); + return false; + } +@@ -51,9 +52,26 @@ bool progress_status_map_insert(progress_status_map *progress_status_map, char * + ERROR("Cannot replace the progress status map item for locking failed"); + return false; + } +- ret = map_insert(progress_status_map->map, key, value); +- progress_status_map_unlock(progress_status_map); + ++ // If the item exists, only replace the value. ++ pval = map_search(progress_status_map->map, key); ++ if (pval != NULL) { ++ pval->dlnow = current; ++ pval->dltotal = total; ++ progress_status_map_unlock(progress_status_map); ++ return true; ++ } ++ pval = util_common_calloc_s(sizeof(progress)); ++ if (pval == NULL) { ++ ERROR("Out of memory"); ++ progress_status_map_unlock(progress_status_map); ++ return false; ++ } ++ pval->dlnow = current; ++ pval->dltotal = total; ++ ++ ret = map_insert(progress_status_map->map, key, pval); ++ progress_status_map_unlock(progress_status_map); + return ret; + } + +diff --git a/src/daemon/modules/image/oci/progress.h b/src/daemon/modules/image/oci/progress.h +index 496a32f3..dcc8e144 100644 +--- a/src/daemon/modules/image/oci/progress.h ++++ b/src/daemon/modules/image/oci/progress.h +@@ -29,11 +29,11 @@ typedef struct progress_status_map { + } progress_status_map; + + typedef struct progress { +- int64_t dlnow; +- int64_t dltotal; ++ int64_t dlnow; ++ int64_t dltotal; + } progress; + +-bool progress_status_map_insert(progress_status_map *progress_status_map, char *key, progress *value); ++bool progress_status_map_udpate(progress_status_map *progress_status_map, char *key, int64_t current, int64_t total); + + progress_status_map *progress_status_map_new(); + +diff --git a/src/daemon/modules/image/oci/registry/http_request.c b/src/daemon/modules/image/oci/registry/http_request.c +index 748c9a9b..450fbc41 100644 +--- a/src/daemon/modules/image/oci/registry/http_request.c ++++ b/src/daemon/modules/image/oci/registry/http_request.c +@@ -692,44 +692,22 @@ out: + static int xfer_inner(void *p, int64_t dltotal, int64_t dlnow, int64_t ultotal, int64_t ulnow) + { + progress_arg *arg = (progress_arg *)p; +- progress *progress_value = NULL; + + if (arg == NULL || arg->map_store == NULL) { + ERROR("Wrong progress arg"); + return -1; + } ++ + // When fetch_manifest_list, there's no digest. It's not a layer pulling progress and skip it. + if (arg->digest == NULL) { + return 0; + } + +- if (!progress_status_map_lock(arg->map_store)) { +- ERROR("Cannot update progress status map for locking failed"); ++ if (!progress_status_map_udpate(arg->map_store, arg->digest, dlnow, dltotal)) { ++ ERROR("Failed to update pull progress"); + return -1; + } + +- // If the item exists, only replace the value. +- progress_value = map_search(arg->map_store->map, arg->digest); +- if (progress_value != NULL) { +- progress_value->dlnow = dlnow; +- progress_value->dltotal = dltotal; +- progress_status_map_unlock(arg->map_store); +- +- return 0; +- } +- progress_status_map_unlock(arg->map_store); +- +- progress_value = util_common_calloc_s(sizeof(progress)); +- if (progress_value == NULL) { +- ERROR("Out of memory"); +- return -1; +- } +- +- progress_value->dlnow = dlnow; +- progress_value->dltotal = dltotal; +- +- progress_status_map_insert(arg->map_store, arg->digest, progress_value); +- + return 0; + } + +diff --git a/src/daemon/modules/image/oci/storage/image_store/image_store.c b/src/daemon/modules/image/oci/storage/image_store/image_store.c +index f49f4707..58baa47a 100644 +--- a/src/daemon/modules/image/oci/storage/image_store/image_store.c ++++ b/src/daemon/modules/image/oci/storage/image_store/image_store.c +@@ -2824,7 +2824,7 @@ static int implicit_digest(map_t *digests, image_t *img) + + // Find whether the manifest in big_data_digests exists, if not, return 0 directly + if (!get_index_by_key((const char **)img->simage->big_data_digests->keys, img->simage->big_data_digests->len, +- IMAGE_DIGEST_BIG_DATA_KEY, &index)) { ++ IMAGE_DIGEST_BIG_DATA_KEY, &index)) { + return 0; + } + +diff --git a/src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2/driver_overlay2.c b/src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2/driver_overlay2.c +index 7517dd43..3bc433ae 100644 +--- a/src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2/driver_overlay2.c ++++ b/src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2/driver_overlay2.c +@@ -1930,7 +1930,7 @@ int overlay2_apply_diff(const char *id, const struct graphdriver *driver, const + goto out; + } + +- ret = archive_unpack(content, layer_diff, &options, root_dir ,&err); ++ ret = archive_unpack(content, layer_diff, &options, root_dir, &err); + if (ret != 0) { + ERROR("Failed to unpack to %s: %s", layer_diff, err); + ret = -1; +diff --git a/src/daemon/modules/image/oci/storage/storage.c b/src/daemon/modules/image/oci/storage/storage.c +index 2e53dbac..0d1a846a 100644 +--- a/src/daemon/modules/image/oci/storage/storage.c ++++ b/src/daemon/modules/image/oci/storage/storage.c +@@ -215,7 +215,7 @@ int storage_inc_hold_refs(const char *layer_id) + int storage_dec_hold_refs(const char *layer_id) + { + int ret = 0; +- ++ + if (layer_id == NULL) { + ERROR("Empty layer id"); + return -1; +@@ -550,7 +550,8 @@ char *storage_img_get_image_id(const char *img_name) + return image_store_lookup(img_name); + } + +-static bool is_top_layer_of_other_image(const char *img_id, const imagetool_images_list *all_images, const char *layer_id) ++static bool is_top_layer_of_other_image(const char *img_id, const imagetool_images_list *all_images, ++ const char *layer_id) + { + size_t i = 0; + +-- +2.42.0 + diff --git a/0028-2230-format-code.patch b/0028-2230-format-code.patch new file mode 100644 index 0000000..e1fb272 --- /dev/null +++ b/0028-2230-format-code.patch @@ -0,0 +1,3476 @@ +From c91b4d223fa590e2d5164b42e12a9bca319831e5 Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Thu, 23 Nov 2023 12:31:47 +0000 +Subject: [PATCH 28/64] !2230 format code * format code tools/static_check.sh + +--- + src/daemon/common/cri/v1/v1_cri_helpers.cc | 8 +- + src/daemon/common/cri/v1/v1_cri_helpers.h | 6 +- + .../common/cri/v1/v1_cri_security_context.cc | 6 +- + .../entry/connect/grpc/cri/cri_service.cc | 2 +- + .../cri/v1/cri_v1_runtime_image_service.cc | 20 +- + .../cri/v1/cri_v1_runtime_runtime_service.cc | 91 +-- + .../v1alpha/cri_runtime_runtime_service.cc | 3 +- + src/daemon/entry/connect/grpc/grpc_service.cc | 2 +- + src/daemon/entry/cri/network_plugin.cc | 4 +- + .../v1/v1_cri_container_manager_service.cc | 10 +- + .../v1/v1_cri_image_manager_service_impl.cc | 6 +- + .../v1/v1_cri_image_manager_service_impl.h | 2 +- + .../v1/v1_cri_pod_sandbox_manager_service.cc | 15 +- + .../v1alpha/cri_container_manager_service.cc | 3 +- + .../cri_pod_sandbox_manager_service.cc | 2 +- + .../entry/cri/v1alpha/cri_security_context.cc | 6 +- + .../entry/cri/v1alpha/v1alpha_cri_helpers.cc | 2 +- + .../executor/container_cb/execution_create.c | 8 +- + .../container_cb/execution_information.c | 5 +- + src/daemon/modules/api/container_api.h | 3 +- + .../modules/container/restore/restore.c | 3 +- + .../cni_operator/libcni/invoke/libcni_exec.c | 2 +- + .../network/cni_operator/libcni/libcni_api.c | 9 +- + .../network/cni_operator/libcni/libcni_api.h | 2 +- + .../cni_operator/libcni/libcni_cached.c | 2 +- + .../cni_operator/libcni/libcni_result_type.c | 2 +- + .../modules/runtime/isula/isula_rt_ops.c | 2 +- + .../modules/runtime/shim/shim_rt_monitor.cc | 2 +- + src/daemon/modules/runtime/shim/shim_rt_ops.c | 2 +- + .../modules/service/service_container.c | 3 +- + .../modules/service/vsock_io_handler.cc | 7 +- + src/daemon/modules/service/vsock_io_handler.h | 6 +- + .../sandboxer/client/grpc_async_wait_call.cc | 11 +- + .../sandboxer/client/grpc_async_wait_call.h | 18 +- + .../sandboxer/client/grpc_sandboxer_client.cc | 56 +- + .../sandboxer/client/grpc_sandboxer_client.h | 6 +- + .../client/grpc_sandboxer_monitor.cc | 10 +- + .../sandboxer/client/grpc_sandboxer_monitor.h | 2 +- + .../controller/shim/shim_controller.cc | 7 +- + src/daemon/sandbox/sandbox.cc | 3 +- + src/daemon/sandbox/sandbox_manager.cc | 3 +- + src/daemon/sandbox/sandbox_manager.h | 3 +- + src/daemon/sandbox/sandbox_ops.cc | 2 +- + src/daemon/sandbox/sandbox_ops.h | 3 +- + src/utils/cpputils/url.cc | 5 +- + src/utils/cutils/error.h | 2 +- + src/utils/cutils/map/map.h | 8 - + src/utils/tar/isulad_tar.c | 9 +- + src/utils/tar/isulad_tar.h | 3 +- + test/cutils/utils_file/utils_file_ut.cc | 2 +- + test/mocks/callback_mock.cc | 8 +- + test/mocks/controller_stub_mock.cc | 516 +++++++++++------- + test/mocks/controller_stub_mock.h | 259 +++++++-- + test/mocks/grpc_async_wait_call_mock.cc | 3 +- + test/mocks/grpc_async_wait_call_mock.h | 2 +- + test/mocks/grpc_sandboxer_client_mock.cc | 15 +- + test/mocks/grpc_sandboxer_client_mock.h | 12 +- + test/mocks/grpc_sandboxer_monitor_mock.cc | 2 +- + test/mocks/isulad_config_mock.h | 2 +- + test/mocks/sandbox_mock.cc | 2 +- + test/mocks/sandbox_mock.h | 2 +- + test/mocks/service_container_api_mock.h | 2 +- + test/mocks/shim_controller_mock.cc | 6 +- + test/mocks/shim_controller_mock.h | 8 +- + test/network/cni_operate/cni_operate_ut.cc | 40 +- + test/network/network_mock.cc | 2 +- + test/sandbox/controller/controller_common.cc | 16 +- + test/sandbox/controller/controller_common.h | 3 +- + .../manager/controller_manager_ut.cc | 27 +- + .../async_wait_call/async_wait_call_ut.cc | 9 +- + .../async_wait_call/dummy_monitor_utils.h | 44 +- + .../sandboxer_client/sandboxer_client_ut.cc | 135 +++-- + .../sandboxer_controller_ut.cc | 18 +- + .../controller/shim/shim_controller_ut.cc | 6 +- + 74 files changed, 963 insertions(+), 575 deletions(-) + +diff --git a/src/daemon/common/cri/v1/v1_cri_helpers.cc b/src/daemon/common/cri/v1/v1_cri_helpers.cc +index 4f2660e8..be06eb0a 100644 +--- a/src/daemon/common/cri/v1/v1_cri_helpers.cc ++++ b/src/daemon/common/cri/v1/v1_cri_helpers.cc +@@ -391,7 +391,7 @@ auto GetSecurityOpts(const commonSecurityContext &context, const char &separator + } + + std::vector selinuxOpts = CRIHelpersV1::GetSELinuxLabelOpts(context.hasSELinuxOption, +- context.selinuxOption, separator, error); ++ context.selinuxOption, separator, error); + if (error.NotEmpty()) { + error.Errorf("Failed to generate SELinuxLabel options for container %s", error.GetMessage().c_str()); + return securityOpts; +@@ -459,7 +459,8 @@ void AddSecurityOptsToHostConfig(std::vector &securityOpts, host_co + } + + } +-void GetContainerSandboxID(const std::string &containerID, std::string &realContainerID, std::string &sandboxID, Errors &error) ++void GetContainerSandboxID(const std::string &containerID, std::string &realContainerID, std::string &sandboxID, ++ Errors &error) + { + std::string PodID; + container_inspect *info = CRIHelpers::InspectContainer(containerID, error, false); +@@ -526,7 +527,8 @@ out: + return sandboxer; + } + +-void ApplySandboxSecurityContextToHostConfig(const runtime::v1::LinuxSandboxSecurityContext &context, host_config *hc, Errors &error) ++void ApplySandboxSecurityContextToHostConfig(const runtime::v1::LinuxSandboxSecurityContext &context, host_config *hc, ++ Errors &error) + { + if (hc == nullptr) { + ERROR("Invalid input arguments: empty hostconfig"); +diff --git a/src/daemon/common/cri/v1/v1_cri_helpers.h b/src/daemon/common/cri/v1/v1_cri_helpers.h +index 0fa1ae91..7085f8d2 100644 +--- a/src/daemon/common/cri/v1/v1_cri_helpers.h ++++ b/src/daemon/common/cri/v1/v1_cri_helpers.h +@@ -73,11 +73,13 @@ auto GetPodSELinuxLabelOpts(const std::string &selinuxLabel, Errors &error) + + void AddSecurityOptsToHostConfig(std::vector &securityOpts, host_config *hostconfig, Errors &error); + +-void GetContainerSandboxID(const std::string &containerID, std::string &realContainerID, std::string &sandboxID, Errors &error); ++void GetContainerSandboxID(const std::string &containerID, std::string &realContainerID, std::string &sandboxID, ++ Errors &error); + + std::string CRISandboxerConvert(const std::string &runtime); + +-void ApplySandboxSecurityContextToHostConfig(const runtime::v1::LinuxSandboxSecurityContext &context, host_config *hc, Errors &error); ++void ApplySandboxSecurityContextToHostConfig(const runtime::v1::LinuxSandboxSecurityContext &context, host_config *hc, ++ Errors &error); + + }; // namespace CRIHelpers + +diff --git a/src/daemon/common/cri/v1/v1_cri_security_context.cc b/src/daemon/common/cri/v1/v1_cri_security_context.cc +index 930710e0..7cdbf5fc 100644 +--- a/src/daemon/common/cri/v1/v1_cri_security_context.cc ++++ b/src/daemon/common/cri/v1/v1_cri_security_context.cc +@@ -19,7 +19,8 @@ + #include + + namespace CRISecurityV1 { +-static void ModifyContainerConfig(const runtime::v1::LinuxContainerSecurityContext &sc, container_config *config, Errors &error) ++static void ModifyContainerConfig(const runtime::v1::LinuxContainerSecurityContext &sc, container_config *config, ++ Errors &error) + { + // none -> ""; username -> username; username, uid -> username; username, uid, gid -> username:gid; + // username, gid -> username:gid; uid -> uid; uid, gid -> uid:gid; gid -> error +@@ -157,7 +158,8 @@ static void ApplyMaskedPathsToHostConfig(const runtime::v1::LinuxContainerSecuri + } + } + +-static void ApplyReadonlyPathsToHostConfig(const runtime::v1::LinuxContainerSecurityContext &sc, host_config *hostConfig, ++static void ApplyReadonlyPathsToHostConfig(const runtime::v1::LinuxContainerSecurityContext &sc, ++ host_config *hostConfig, + Errors &error) + { + if (sc.readonly_paths_size() <= 0) { +diff --git a/src/daemon/entry/connect/grpc/cri/cri_service.cc b/src/daemon/entry/connect/grpc/cri/cri_service.cc +index e33a6d34..c1986c44 100644 +--- a/src/daemon/entry/connect/grpc/cri/cri_service.cc ++++ b/src/daemon/entry/connect/grpc/cri/cri_service.cc +@@ -50,7 +50,7 @@ int CRIService::Init(const isulad_daemon_configs *config) + } + + Errors err; +- /* note: get config from args, now use defaults */ ++ /* note: get config from args, now use defaults */ + Network::NetworkPluginConf mConf; + + if (config != nullptr) { +diff --git a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_image_service.cc b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_image_service.cc +index ac62b6eb..09c8958d 100644 +--- a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_image_service.cc ++++ b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_image_service.cc +@@ -28,8 +28,8 @@ RuntimeV1ImageServiceImpl::RuntimeV1ImageServiceImpl() + } + + grpc::Status RuntimeV1ImageServiceImpl::PullImage(grpc::ServerContext *context, +- const runtime::v1::PullImageRequest *request, +- runtime::v1::PullImageResponse *reply) ++ const runtime::v1::PullImageRequest *request, ++ runtime::v1::PullImageResponse *reply) + { + Errors error; + +@@ -53,8 +53,8 @@ grpc::Status RuntimeV1ImageServiceImpl::PullImage(grpc::ServerContext *context, + } + + grpc::Status RuntimeV1ImageServiceImpl::ListImages(grpc::ServerContext *context, +- const runtime::v1::ListImagesRequest *request, +- runtime::v1::ListImagesResponse *reply) ++ const runtime::v1::ListImagesRequest *request, ++ runtime::v1::ListImagesResponse *reply) + { + std::vector> images; + Errors error; +@@ -86,8 +86,8 @@ grpc::Status RuntimeV1ImageServiceImpl::ListImages(grpc::ServerContext *context, + } + + grpc::Status RuntimeV1ImageServiceImpl::ImageStatus(grpc::ServerContext *context, +- const runtime::v1::ImageStatusRequest *request, +- runtime::v1::ImageStatusResponse *reply) ++ const runtime::v1::ImageStatusRequest *request, ++ runtime::v1::ImageStatusResponse *reply) + { + std::unique_ptr image_info = nullptr; + Errors error; +@@ -117,8 +117,8 @@ grpc::Status RuntimeV1ImageServiceImpl::ImageStatus(grpc::ServerContext *context + } + + grpc::Status RuntimeV1ImageServiceImpl::ImageFsInfo(grpc::ServerContext *context, +- const runtime::v1::ImageFsInfoRequest *request, +- runtime::v1::ImageFsInfoResponse *reply) ++ const runtime::v1::ImageFsInfoRequest *request, ++ runtime::v1::ImageFsInfoResponse *reply) + { + std::vector> usages; + Errors error; +@@ -150,8 +150,8 @@ grpc::Status RuntimeV1ImageServiceImpl::ImageFsInfo(grpc::ServerContext *context + } + + grpc::Status RuntimeV1ImageServiceImpl::RemoveImage(grpc::ServerContext *context, +- const runtime::v1::RemoveImageRequest *request, +- runtime::v1::RemoveImageResponse *reply) ++ const runtime::v1::RemoveImageRequest *request, ++ runtime::v1::RemoveImageResponse *reply) + { + Errors error; + +diff --git a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc +index 1db79307..ba9459f6 100644 +--- a/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc ++++ b/src/daemon/entry/connect/grpc/cri/v1/cri_v1_runtime_runtime_service.cc +@@ -25,7 +25,8 @@ + + using namespace CRIV1; + +-void RuntimeV1RuntimeServiceImpl::Init(std::string &podSandboxImage, std::shared_ptr networkPlugin, Errors &err) ++void RuntimeV1RuntimeServiceImpl::Init(std::string &podSandboxImage, ++ std::shared_ptr networkPlugin, Errors &err) + { + // Assembly implementation for CRIRuntimeServiceImpl + service_executor_t *cb = get_service_executor(); +@@ -47,8 +48,8 @@ void RuntimeV1RuntimeServiceImpl::Shutdown() + } + + grpc::Status RuntimeV1RuntimeServiceImpl::Version(grpc::ServerContext *context, +- const runtime::v1::VersionRequest *request, +- runtime::v1::VersionResponse *reply) ++ const runtime::v1::VersionRequest *request, ++ runtime::v1::VersionResponse *reply) + { + Errors error; + if (request == nullptr || reply == nullptr) { +@@ -65,8 +66,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::Version(grpc::ServerContext *context, + } + + grpc::Status RuntimeV1RuntimeServiceImpl::CreateContainer(grpc::ServerContext *context, +- const runtime::v1::CreateContainerRequest *request, +- runtime::v1::CreateContainerResponse *reply) ++ const runtime::v1::CreateContainerRequest *request, ++ runtime::v1::CreateContainerResponse *reply) + { + Errors error; + +@@ -91,8 +92,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::CreateContainer(grpc::ServerContext *c + } + + grpc::Status RuntimeV1RuntimeServiceImpl::StartContainer(grpc::ServerContext *context, +- const runtime::v1::StartContainerRequest *request, +- runtime::v1::StartContainerResponse *reply) ++ const runtime::v1::StartContainerRequest *request, ++ runtime::v1::StartContainerResponse *reply) + { + Errors error; + +@@ -115,8 +116,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::StartContainer(grpc::ServerContext *co + } + + grpc::Status RuntimeV1RuntimeServiceImpl::StopContainer(grpc::ServerContext *context, +- const runtime::v1::StopContainerRequest *request, +- runtime::v1::StopContainerResponse *reply) ++ const runtime::v1::StopContainerRequest *request, ++ runtime::v1::StopContainerResponse *reply) + { + Errors error; + +@@ -139,8 +140,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::StopContainer(grpc::ServerContext *con + } + + grpc::Status RuntimeV1RuntimeServiceImpl::RemoveContainer(grpc::ServerContext *context, +- const runtime::v1::RemoveContainerRequest *request, +- runtime::v1::RemoveContainerResponse *reply) ++ const runtime::v1::RemoveContainerRequest *request, ++ runtime::v1::RemoveContainerResponse *reply) + { + Errors error; + +@@ -163,8 +164,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::RemoveContainer(grpc::ServerContext *c + } + + grpc::Status RuntimeV1RuntimeServiceImpl::ListContainers(grpc::ServerContext *context, +- const runtime::v1::ListContainersRequest *request, +- runtime::v1::ListContainersResponse *reply) ++ const runtime::v1::ListContainersRequest *request, ++ runtime::v1::ListContainersResponse *reply) + { + Errors error; + +@@ -197,8 +198,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::ListContainers(grpc::ServerContext *co + } + + grpc::Status RuntimeV1RuntimeServiceImpl::ContainerStats(grpc::ServerContext *context, +- const runtime::v1::ContainerStatsRequest *request, +- runtime::v1::ContainerStatsResponse *reply) ++ const runtime::v1::ContainerStatsRequest *request, ++ runtime::v1::ContainerStatsResponse *reply) + { + Errors error; + +@@ -223,8 +224,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::ContainerStats(grpc::ServerContext *co + } + + grpc::Status RuntimeV1RuntimeServiceImpl::ListContainerStats(grpc::ServerContext *context, +- const runtime::v1::ListContainerStatsRequest *request, +- runtime::v1::ListContainerStatsResponse *reply) ++ const runtime::v1::ListContainerStatsRequest *request, ++ runtime::v1::ListContainerStatsResponse *reply) + { + Errors error; + +@@ -257,8 +258,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::ListContainerStats(grpc::ServerContext + } + + grpc::Status RuntimeV1RuntimeServiceImpl::ContainerStatus(grpc::ServerContext *context, +- const runtime::v1::ContainerStatusRequest *request, +- runtime::v1::ContainerStatusResponse *reply) ++ const runtime::v1::ContainerStatusRequest *request, ++ runtime::v1::ContainerStatusResponse *reply) + { + Errors error; + +@@ -283,8 +284,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::ContainerStatus(grpc::ServerContext *c + } + + grpc::Status RuntimeV1RuntimeServiceImpl::ExecSync(grpc::ServerContext *context, +- const runtime::v1::ExecSyncRequest *request, +- runtime::v1::ExecSyncResponse *reply) ++ const runtime::v1::ExecSyncRequest *request, ++ runtime::v1::ExecSyncResponse *reply) + { + Errors error; + +@@ -307,8 +308,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::ExecSync(grpc::ServerContext *context, + } + + grpc::Status RuntimeV1RuntimeServiceImpl::RunPodSandbox(grpc::ServerContext *context, +- const runtime::v1::RunPodSandboxRequest *request, +- runtime::v1::RunPodSandboxResponse *reply) ++ const runtime::v1::RunPodSandboxRequest *request, ++ runtime::v1::RunPodSandboxResponse *reply) + { + Errors error; + +@@ -335,8 +336,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::RunPodSandbox(grpc::ServerContext *con + } + + grpc::Status RuntimeV1RuntimeServiceImpl::StopPodSandbox(grpc::ServerContext *context, +- const runtime::v1::StopPodSandboxRequest *request, +- runtime::v1::StopPodSandboxResponse *reply) ++ const runtime::v1::StopPodSandboxRequest *request, ++ runtime::v1::StopPodSandboxResponse *reply) + { + Errors error; + +@@ -360,8 +361,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::StopPodSandbox(grpc::ServerContext *co + } + + grpc::Status RuntimeV1RuntimeServiceImpl::RemovePodSandbox(grpc::ServerContext *context, +- const runtime::v1::RemovePodSandboxRequest *request, +- runtime::v1::RemovePodSandboxResponse *reply) ++ const runtime::v1::RemovePodSandboxRequest *request, ++ runtime::v1::RemovePodSandboxResponse *reply) + { + Errors error; + +@@ -385,8 +386,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::RemovePodSandbox(grpc::ServerContext * + } + + grpc::Status RuntimeV1RuntimeServiceImpl::PodSandboxStatus(grpc::ServerContext *context, +- const runtime::v1::PodSandboxStatusRequest *request, +- runtime::v1::PodSandboxStatusResponse *reply) ++ const runtime::v1::PodSandboxStatusRequest *request, ++ runtime::v1::PodSandboxStatusResponse *reply) + { + Errors error; + +@@ -412,8 +413,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::PodSandboxStatus(grpc::ServerContext * + } + + grpc::Status RuntimeV1RuntimeServiceImpl::ListPodSandbox(grpc::ServerContext *context, +- const runtime::v1::ListPodSandboxRequest *request, +- runtime::v1::ListPodSandboxResponse *reply) ++ const runtime::v1::ListPodSandboxRequest *request, ++ runtime::v1::ListPodSandboxResponse *reply) + { + Errors error; + +@@ -446,8 +447,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::ListPodSandbox(grpc::ServerContext *co + } + + grpc::Status RuntimeV1RuntimeServiceImpl::PodSandboxStats(grpc::ServerContext *context, +- const runtime::v1::PodSandboxStatsRequest *request, +- runtime::v1::PodSandboxStatsResponse *reply) ++ const runtime::v1::PodSandboxStatsRequest *request, ++ runtime::v1::PodSandboxStatsResponse *reply) + { + Errors error; + +@@ -474,8 +475,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::PodSandboxStats(grpc::ServerContext *c + + grpc::Status + RuntimeV1RuntimeServiceImpl::ListPodSandboxStats(grpc::ServerContext *context, +- const runtime::v1::ListPodSandboxStatsRequest *request, +- runtime::v1::ListPodSandboxStatsResponse *reply) ++ const runtime::v1::ListPodSandboxStatsRequest *request, ++ runtime::v1::ListPodSandboxStatsResponse *reply) + { + Errors error; + +@@ -508,8 +509,8 @@ RuntimeV1RuntimeServiceImpl::ListPodSandboxStats(grpc::ServerContext *context, + + grpc::Status + RuntimeV1RuntimeServiceImpl::UpdateContainerResources(grpc::ServerContext *context, +- const runtime::v1::UpdateContainerResourcesRequest *request, +- runtime::v1::UpdateContainerResourcesResponse *reply) ++ const runtime::v1::UpdateContainerResourcesRequest *request, ++ runtime::v1::UpdateContainerResourcesResponse *reply) + { + Errors error; + +@@ -533,8 +534,8 @@ RuntimeV1RuntimeServiceImpl::UpdateContainerResources(grpc::ServerContext *conte + } + + grpc::Status RuntimeV1RuntimeServiceImpl::Exec(grpc::ServerContext *context, +- const runtime::v1::ExecRequest *request, +- runtime::v1::ExecResponse *response) ++ const runtime::v1::ExecRequest *request, ++ runtime::v1::ExecResponse *response) + { + Errors error; + +@@ -558,8 +559,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::Exec(grpc::ServerContext *context, + } + + grpc::Status RuntimeV1RuntimeServiceImpl::Attach(grpc::ServerContext *context, +- const runtime::v1::AttachRequest *request, +- runtime::v1::AttachResponse *response) ++ const runtime::v1::AttachRequest *request, ++ runtime::v1::AttachResponse *response) + { + Errors error; + +@@ -584,8 +585,8 @@ grpc::Status RuntimeV1RuntimeServiceImpl::Attach(grpc::ServerContext *context, + + grpc::Status + RuntimeV1RuntimeServiceImpl::UpdateRuntimeConfig(grpc::ServerContext *context, +- const runtime::v1::UpdateRuntimeConfigRequest *request, +- runtime::v1::UpdateRuntimeConfigResponse *reply) ++ const runtime::v1::UpdateRuntimeConfigRequest *request, ++ runtime::v1::UpdateRuntimeConfigResponse *reply) + { + Errors error; + +@@ -608,8 +609,8 @@ RuntimeV1RuntimeServiceImpl::UpdateRuntimeConfig(grpc::ServerContext *context, + } + + grpc::Status RuntimeV1RuntimeServiceImpl::Status(grpc::ServerContext *context, +- const runtime::v1::StatusRequest *request, +- runtime::v1::StatusResponse *reply) ++ const runtime::v1::StatusRequest *request, ++ runtime::v1::StatusResponse *reply) + { + Errors error; + +diff --git a/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.cc b/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.cc +index a56b167c..5e85702c 100644 +--- a/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.cc ++++ b/src/daemon/entry/connect/grpc/cri/v1alpha/cri_runtime_runtime_service.cc +@@ -23,7 +23,8 @@ + + using namespace CRI; + +-void RuntimeRuntimeServiceImpl::Init(std::string &podSandboxImage, std::shared_ptr networkPlugin, Errors &err) ++void RuntimeRuntimeServiceImpl::Init(std::string &podSandboxImage, ++ std::shared_ptr networkPlugin, Errors &err) + { + // Assembly implementation for CRIRuntimeServiceImpl + service_executor_t *cb = get_service_executor(); +diff --git a/src/daemon/entry/connect/grpc/grpc_service.cc b/src/daemon/entry/connect/grpc/grpc_service.cc +index 4e1ae019..61e284f3 100644 +--- a/src/daemon/entry/connect/grpc/grpc_service.cc ++++ b/src/daemon/entry/connect/grpc/grpc_service.cc +@@ -109,7 +109,7 @@ public: + void Shutdown(void) + { + m_server->Shutdown(); +- ++ + // call CRI to shutdown stream server + m_criService.Shutdown(); + +diff --git a/src/daemon/entry/cri/network_plugin.cc b/src/daemon/entry/cri/network_plugin.cc +index f919a059..f8f9c7e6 100644 +--- a/src/daemon/entry/cri/network_plugin.cc ++++ b/src/daemon/entry/cri/network_plugin.cc +@@ -558,14 +558,14 @@ void NoopNetworkPlugin::SetUpPod(const std::string &ns, const std::string &name, + } + + container_network_settings *network_settings = static_cast +- (util_common_calloc_s(sizeof(container_network_settings))); ++ (util_common_calloc_s(sizeof(container_network_settings))); + if (network_settings == nullptr) { + ERROR("Out of memory"); + error.SetError("Out of memory"); + return; + } + auto settingsWarpper = std::unique_ptr>(new +- CStructWrapper(network_settings, free_container_network_settings)); ++ CStructWrapper(network_settings, free_container_network_settings)); + + network_settings->sandbox_key = util_strdup_s(netnsPath.c_str()); + +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 f635df2b..067f4210 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 +@@ -149,7 +149,7 @@ void ContainerManagerService::DoUsePodLevelSELinuxConfig(const runtime::v1::Cont + auto ContainerManagerService::IsSELinuxLabelEmpty(const ::runtime::v1::SELinuxOption &selinuxOption) -> bool + { + return selinuxOption.user().length() == 0 && selinuxOption.role().length() == 0 && +- selinuxOption.type().length() == 0 && selinuxOption.level().length() == 0; ++ selinuxOption.type().length() == 0 && selinuxOption.level().length() == 0; + } + + auto ContainerManagerService::GenerateCreateContainerHostConfig( +@@ -194,7 +194,7 @@ auto ContainerManagerService::GenerateCreateContainerHostConfig( + DoUsePodLevelSELinuxConfig(containerConfig, hostconfig, sandbox, error); + if (error.NotEmpty()) { + ERROR("Failed to add pod: %s security context to host config for container: %s", +- sandbox.GetName().c_str(), containerConfig.metadata().name().c_str()); ++ sandbox.GetName().c_str(), containerConfig.metadata().name().c_str()); + goto cleanup; + } + } +@@ -539,8 +539,10 @@ void ContainerManagerService::CreateContainerLogSymlink(const std::string &conta + WARN("Deleted previously existing symlink file: %s", path); + } + if (symlink(realPath, path) != 0) { +- SYSERROR("failed to create symbolic link %s to the container log file %s for container %s", path, realPath, containerID.c_str()); +- error.Errorf("failed to create symbolic link %s to the container log file %s for container %s", path, realPath, containerID.c_str()); ++ SYSERROR("failed to create symbolic link %s to the container log file %s for container %s", path, realPath, ++ containerID.c_str()); ++ error.Errorf("failed to create symbolic link %s to the container log file %s for container %s", path, realPath, ++ containerID.c_str()); + goto cleanup; + } + } else { +diff --git a/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.cc b/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.cc +index 066eed5e..71918706 100644 +--- a/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.cc ++++ b/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.cc +@@ -202,7 +202,7 @@ auto ImageManagerServiceImpl::status_request_from_grpc(const runtime::v1::ImageS + } + + std::unique_ptr ImageManagerServiceImpl::status_image_to_grpc(im_summary_response *response, +- Errors & /*error*/) ++ Errors & /*error*/) + { + imagetool_image_summary *image_info = response->image_summary; + if (image_info == nullptr) { +@@ -220,8 +220,8 @@ std::unique_ptr ImageManagerServiceImpl::status_image_to_grp + } + + std::unique_ptr ImageManagerServiceImpl::ImageStatus(const runtime::v1::ImageSpec +- &image, +- Errors &error) ++ &image, ++ Errors &error) + { + im_summary_request *request { nullptr }; + im_summary_response *response { nullptr }; +diff --git a/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.h b/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.h +index 3f13a157..1c276e06 100644 +--- a/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.h ++++ b/src/daemon/entry/cri/v1/v1_cri_image_manager_service_impl.h +@@ -33,7 +33,7 @@ public: + std::vector> &images, Errors &error) override; + + std::unique_ptr ImageStatus(const runtime::v1::ImageSpec &image, +- Errors &error) override; ++ Errors &error) override; + + std::string PullImage(const runtime::v1::ImageSpec &image, const runtime::v1::AuthConfig &auth, + Errors &error) override; +diff --git a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc +index 2c802900..0f6b8508 100644 +--- a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc ++++ b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc +@@ -196,7 +196,8 @@ void PodSandboxManagerService::UpdateSandboxConfig(runtime::v1::PodSandboxConfig + // TODO: Update SecurityContext with default values + } + +-void PodSandboxManagerService::SetupSandboxFiles(const std::string &resolvPath, const runtime::v1::PodSandboxConfig &config, Errors &error) ++void PodSandboxManagerService::SetupSandboxFiles(const std::string &resolvPath, ++ const runtime::v1::PodSandboxConfig &config, Errors &error) + { + if (resolvPath.empty()) { + return; +@@ -423,7 +424,8 @@ void PodSandboxManagerService::ClearCniNetwork(const std::shared_ptr(CRIHelpers::Constants::POD_SANDBOX_KEY, sandboxKey)); + + Errors pluginErr; +- m_pluginManager->TearDownPod(config.metadata().namespace_(), config.metadata().name(), Network::DEFAULT_NETWORK_INTERFACE_NAME, ++ m_pluginManager->TearDownPod(config.metadata().namespace_(), config.metadata().name(), ++ Network::DEFAULT_NETWORK_INTERFACE_NAME, + sandbox->GetId(), stdAnnos, pluginErr); + if (pluginErr.NotEmpty()) { + WARN("TearDownPod cni network failed: %s", pluginErr.GetCMessage()); +@@ -492,7 +494,8 @@ auto PodSandboxManagerService::GetContainerListResponse(const std::string &readS + } + + ret = m_cb->container.list(list_request, &list_response); +- auto list_response_wrapper = makeUniquePtrCStructWrapper(list_response, free_container_list_response); ++ auto list_response_wrapper = makeUniquePtrCStructWrapper(list_response, ++ free_container_list_response); + if (list_response_wrapper == nullptr) { + ERROR("Failed to call list container callback"); + errors.push_back("Failed to call list container callback"); +@@ -510,7 +513,7 @@ auto PodSandboxManagerService::GetContainerListResponse(const std::string &readS + } + + return list_response_wrapper; +-} ++} + + auto PodSandboxManagerService::StopAllContainersInSandbox(const std::string &readSandboxID, + Errors &error) -> int +@@ -751,8 +754,8 @@ void PodSandboxManagerService::GetIPs(std::shared_ptr sandbox, + return; + } + +- auto settings = std::unique_ptr>(new +- CStructWrapper(network_settings, free_container_network_settings)); ++ auto settings = std::unique_ptr>(new ++ CStructWrapper(network_settings, free_container_network_settings)); + if (settings == nullptr) { + ERROR("Out of memory"); + return; +diff --git a/src/daemon/entry/cri/v1alpha/cri_container_manager_service.cc b/src/daemon/entry/cri/v1alpha/cri_container_manager_service.cc +index 9da25768..b0abdb52 100644 +--- a/src/daemon/entry/cri/v1alpha/cri_container_manager_service.cc ++++ b/src/daemon/entry/cri/v1alpha/cri_container_manager_service.cc +@@ -547,7 +547,8 @@ void ContainerManagerService::CreateContainerLogSymlink(const std::string &conta + WARN("Deleted previously existing symlink file: %s", path); + } + if (symlink(realPath, path) != 0) { +- SYSERROR("failed to create symbolic link %s to the container log file %s for container %s", path, realPath, containerID.c_str()); ++ SYSERROR("failed to create symbolic link %s to the container log file %s for container %s", path, realPath, ++ containerID.c_str()); + error.Errorf("failed to create symbolic link %s to the container log file %s for container %s: %s", path, + realPath, containerID.c_str()); + goto cleanup; +diff --git a/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc b/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc +index 8eff22ac..bc40cb06 100644 +--- a/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc ++++ b/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc +@@ -569,7 +569,7 @@ void PodSandboxManagerService::UpdatePodSandboxNetworkSettings(const std::string + } + + auto req = (container_update_network_settings_request *)util_common_calloc_s( +- sizeof(container_update_network_settings_request)); ++ sizeof(container_update_network_settings_request)); + if (req == nullptr) { + error.Errorf("container update network settings request: Out of memory"); + return; +diff --git a/src/daemon/entry/cri/v1alpha/cri_security_context.cc b/src/daemon/entry/cri/v1alpha/cri_security_context.cc +index 57ec3a63..2b6c42fe 100644 +--- a/src/daemon/entry/cri/v1alpha/cri_security_context.cc ++++ b/src/daemon/entry/cri/v1alpha/cri_security_context.cc +@@ -130,7 +130,8 @@ static void ModifyHostConfigscSupplementalGroups(const runtime::v1alpha2::LinuxC + } + } + +-static void ApplyMaskedPathsToHostConfig(const runtime::v1alpha2::LinuxContainerSecurityContext &sc, host_config *hostConfig, ++static void ApplyMaskedPathsToHostConfig(const runtime::v1alpha2::LinuxContainerSecurityContext &sc, ++ host_config *hostConfig, + Errors &error) + { + if (sc.masked_paths_size() <= 0) { +@@ -159,7 +160,8 @@ static void ApplyMaskedPathsToHostConfig(const runtime::v1alpha2::LinuxContainer + } + } + +-static void ApplyReadonlyPathsToHostConfig(const runtime::v1alpha2::LinuxContainerSecurityContext &sc, host_config *hostConfig, ++static void ApplyReadonlyPathsToHostConfig(const runtime::v1alpha2::LinuxContainerSecurityContext &sc, ++ host_config *hostConfig, + Errors &error) + { + if (sc.readonly_paths_size() <= 0) { +diff --git a/src/daemon/entry/cri/v1alpha/v1alpha_cri_helpers.cc b/src/daemon/entry/cri/v1alpha/v1alpha_cri_helpers.cc +index e55e46f0..b06092a7 100644 +--- a/src/daemon/entry/cri/v1alpha/v1alpha_cri_helpers.cc ++++ b/src/daemon/entry/cri/v1alpha/v1alpha_cri_helpers.cc +@@ -392,7 +392,7 @@ auto GetSecurityOpts(const commonSecurityContext &context, const char &separator + } + + std::vector selinuxOpts = CRIHelpersV1Alpha::GetSELinuxLabelOpts(context.hasSELinuxOption, +- context.selinuxOption, separator, error); ++ context.selinuxOption, separator, error); + if (error.NotEmpty()) { + error.Errorf("Failed to generate SELinuxLabel options for container %s", error.GetMessage().c_str()); + return securityOpts; +diff --git a/src/daemon/executor/container_cb/execution_create.c b/src/daemon/executor/container_cb/execution_create.c +index 4b6f62de..6b6c3b75 100644 +--- a/src/daemon/executor/container_cb/execution_create.c ++++ b/src/daemon/executor/container_cb/execution_create.c +@@ -766,8 +766,8 @@ static int maintain_container_id(const container_create_request *request, char * + used_id = container_name_index_get(name); + ERROR("Name %s is in use by container %s", name, used_id); + isulad_set_error_message("Conflict. The name \"%s\" is already in use by container %s. " +- "You have to remove (or rename) that container to be able to reuse that name.", +- name, used_id); ++ "You have to remove (or rename) that container to be able to reuse that name.", ++ name, used_id); + free(used_id); + used_id = NULL; + ret = -1; +@@ -1342,7 +1342,7 @@ static int v2_spec_fill_sandbox_info(const container_sandbox_info *sandbox_info, + return 0; + } + +- if(dup_container_sandbox_info(sandbox_info, &v2_spec->sandbox_info) != 0) { ++ if (dup_container_sandbox_info(sandbox_info, &v2_spec->sandbox_info) != 0) { + ERROR("Failed to dup sandbox info"); + return -1; + } +@@ -1431,7 +1431,7 @@ int container_create_cb(const container_create_request *request, container_creat + v2_spec_fill_basic_info(id, name, image_name, image_type, container_spec, v2_spec); + + #ifdef ENABLE_CRI_API_V1 +- if(v2_spec_fill_sandbox_info(request->sandbox, v2_spec) != 0) { ++ if (v2_spec_fill_sandbox_info(request->sandbox, v2_spec) != 0) { + ERROR("Failed to fill sandbox info"); + cc = ISULAD_ERR_INPUT; + goto clean_container_root_dir; +diff --git a/src/daemon/executor/container_cb/execution_information.c b/src/daemon/executor/container_cb/execution_information.c +index 95f522c6..420f08df 100644 +--- a/src/daemon/executor/container_cb/execution_information.c ++++ b/src/daemon/executor/container_cb/execution_information.c +@@ -250,7 +250,7 @@ static int get_proxy_env(char **proxy, const char *type) + *proxy = NULL; + goto out; + } +- ++ + out: + util_free_sensitive_string(tmp_proxy); + return ret; +@@ -634,7 +634,8 @@ out: + return pid_arg; + } + +-static int get_pids(const char *name, const char *runtime, const char *rootpath, const char *statepath, pid_t **pids, size_t *pids_len, ++static int get_pids(const char *name, const char *runtime, const char *rootpath, const char *statepath, pid_t **pids, ++ size_t *pids_len, + char **pid_args) + { + int ret = 0; +diff --git a/src/daemon/modules/api/container_api.h b/src/daemon/modules/api/container_api.h +index 49849c2d..8e3cd7ac 100644 +--- a/src/daemon/modules/api/container_api.h ++++ b/src/daemon/modules/api/container_api.h +@@ -284,7 +284,8 @@ bool container_is_in_gc_progress(const char *id); + int container_module_init(); + + #ifdef ENABLE_CRI_API_V1 +-static inline bool is_sandbox_container(container_sandbox_info *sandbox) { ++static inline bool is_sandbox_container(container_sandbox_info *sandbox) ++{ + return sandbox != NULL && sandbox->is_sandbox_container; + } + #endif +diff --git a/src/daemon/modules/container/restore/restore.c b/src/daemon/modules/container/restore/restore.c +index a60b1410..fad5b071 100644 +--- a/src/daemon/modules/container/restore/restore.c ++++ b/src/daemon/modules/container/restore/restore.c +@@ -291,7 +291,8 @@ static void restore_state(container_t *cont) + } + } + if (tempret != 0) { +- WARN("Failed to restore container %s, make real status to STOPPED. Due to cannot load container with status %d", id, status); ++ WARN("Failed to restore container %s, make real status to STOPPED. Due to cannot load container with status %d", id, ++ status); + real_status.status = RUNTIME_CONTAINER_STATUS_STOPPED; + } + } +diff --git a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c +index 4908565e..74d6d74a 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c ++++ b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c +@@ -482,7 +482,7 @@ static int do_parse_version_info_stdout_str(int exec_ret, const cni_exec_error * + const char *stdout_str, cni_version_info **result_version) + { + __isula_auto_free char *err_msg = NULL; +- struct parser_context ctx = { OPT_GEN_SIMPLIFY, 0 }; ++ struct parser_context ctx = { OPT_GEN_SIMPLIFY, 0 }; + __isula_auto_free parser_error perr = NULL; + + if (exec_ret != 0) { +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 7f62df78..068881be 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/libcni_api.c ++++ b/src/daemon/modules/network/cni_operator/libcni/libcni_api.c +@@ -209,7 +209,7 @@ static int inject_cni_aliases(const struct runtime_conf *rt, cni_net_conf_runtim + } + + for (i = 0; i < rt->aliases_len; i++) { +- rt_config->aliases[i]= util_strdup_s(rt->aliases[i]); ++ rt_config->aliases[i] = util_strdup_s(rt->aliases[i]); + } + rt_config->aliases_len = rt->aliases_len; + return 0; +@@ -472,7 +472,7 @@ static int find_plugin_in_path(const char *plugin, const char * const *paths, si + ERROR("Invalid plugin name: %s", plugin); + return -1; + } +- ++ + for (i = 0; i < len; i++) { + if (do_check_file(plugin, paths[i], find_path) == 0) { + ret = 0; +@@ -689,7 +689,8 @@ int cni_add_network_list(const struct cni_network_list_conf *list, const struct + } + } + +- if (*pret != NULL && version_greater_than_or_equal_to((*pret)->cniversion, SUPPORT_CACHE_AND_CHECK_VERSION, &greater) != 0) { ++ if (*pret != NULL && ++ version_greater_than_or_equal_to((*pret)->cniversion, SUPPORT_CACHE_AND_CHECK_VERSION, &greater) != 0) { + return 0; + } + +@@ -867,7 +868,7 @@ static int version_network(const char *plugin_name, cni_version_info **result_ve + } + + int cni_version_network_list(const struct cni_network_list_conf *list, +- struct cni_version_info_list **result_version_list) ++ struct cni_version_info_list **result_version_list) + { + int ret = 0; + int i; +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 f94ab3f7..2f10d6e9 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/libcni_api.h ++++ b/src/daemon/modules/network/cni_operator/libcni/libcni_api.h +@@ -84,7 +84,7 @@ int cni_del_network_list(const struct cni_network_list_conf *list, const struct + + int cni_check_network_list(const struct cni_network_list_conf *list, const struct runtime_conf *rc, + struct cni_opt_result **p_result); +- ++ + int cni_version_network_list(const struct cni_network_list_conf *list, + struct cni_version_info_list **result_version_list); + +diff --git a/src/daemon/modules/network/cni_operator/libcni/libcni_cached.c b/src/daemon/modules/network/cni_operator/libcni/libcni_cached.c +index 222511d6..1457c9be 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/libcni_cached.c ++++ b/src/daemon/modules/network/cni_operator/libcni/libcni_cached.c +@@ -205,7 +205,7 @@ static int do_cache_insert_aliases(const struct runtime_conf *rc, cni_cached_inf + return -1; + } + +- for (i = 0; i < rc->aliases_len; i++){ ++ for (i = 0; i < rc->aliases_len; i++) { + tmp_aliases[i] = util_strdup_s(rc->aliases[i]); + } + +diff --git a/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c b/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c +index 8a0ce1dd..2365a128 100644 +--- a/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c ++++ b/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c +@@ -137,7 +137,7 @@ void free_cni_version_info_list(struct cni_version_info_list *val) + if (val == NULL) { + return; + } +- ++ + for (i = 0; i < val->result_versions_len; i++) { + free_cni_version_info(val->result_versions[i]); + val->result_versions[i] = NULL; +diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c +index e61d1f91..859356e5 100644 +--- a/src/daemon/modules/runtime/isula/isula_rt_ops.c ++++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c +@@ -1495,7 +1495,7 @@ static int get_attach_socketfd(const char *attach_socket, int *socket_fd) + + if (strlen(attach_socket) >= sizeof(addr.sun_path)) { + SYSERROR("Invalid attach socket path: %s", attach_socket); +- return -1; ++ return -1; + } + + tmp_socket = socket(AF_UNIX, SOCK_STREAM, 0); +diff --git a/src/daemon/modules/runtime/shim/shim_rt_monitor.cc b/src/daemon/modules/runtime/shim/shim_rt_monitor.cc +index f5178c26..2547a206 100644 +--- a/src/daemon/modules/runtime/shim/shim_rt_monitor.cc ++++ b/src/daemon/modules/runtime/shim/shim_rt_monitor.cc +@@ -31,7 +31,7 @@ + #include "error.h" + + extern "C" { +- #include ++#include + } + + struct shim_monitor_data { +diff --git a/src/daemon/modules/runtime/shim/shim_rt_ops.c b/src/daemon/modules/runtime/shim/shim_rt_ops.c +index 56fc43c2..1bc9dc54 100644 +--- a/src/daemon/modules/runtime/shim/shim_rt_ops.c ++++ b/src/daemon/modules/runtime/shim/shim_rt_ops.c +@@ -395,7 +395,7 @@ int rt_shim_create(const char *id, const char *runtime, const rt_create_params_t + + /** + * If task address is not set, create a new shim-v2 and get the address. +- * If task address is set, use it directly. ++ * If task address is set, use it directly. + */ + if (params->task_addr == NULL || strlen(params->task_addr) == 0) { + if (shim_bin_v2_create(runtime, id, params->bundle, NULL, response, state_path) != 0) { +diff --git a/src/daemon/modules/service/service_container.c b/src/daemon/modules/service/service_container.c +index 01427ddf..97f73768 100644 +--- a/src/daemon/modules/service/service_container.c ++++ b/src/daemon/modules/service/service_container.c +@@ -2197,7 +2197,8 @@ static int exec_prepare_console(const container_t *cont, const container_exec_re + return exec_prepare_vsock(cont, request, stdinfd, stdout_handler, stderr_handler, io_addresses, sync_fd, thread_id); + } + #endif +- return exec_prepare_fifo(cont, request, stdinfd, stdout_handler, stderr_handler, io_addresses, iopath, sync_fd, thread_id); ++ return exec_prepare_fifo(cont, request, stdinfd, stdout_handler, stderr_handler, io_addresses, iopath, sync_fd, ++ thread_id); + } + + static void exec_container_end(container_exec_response *response, const container_t *cont, +diff --git a/src/daemon/modules/service/vsock_io_handler.cc b/src/daemon/modules/service/vsock_io_handler.cc +index efc74bc8..2c73490a 100644 +--- a/src/daemon/modules/service/vsock_io_handler.cc ++++ b/src/daemon/modules/service/vsock_io_handler.cc +@@ -165,7 +165,7 @@ static int vsock_connect(uint32_t cid, uint32_t port) + sa.svm_cid = cid; + sa.svm_port = port; + +- if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) !=0) { ++ if (connect(fd, (struct sockaddr *)&sa, sizeof(sa)) != 0) { + SYSERROR("Failed to connect vsock socket"); + close(fd); + return -1; +@@ -314,7 +314,7 @@ void delete_daemon_vsockpaths(const char *sandbox_id, const char *vsockpaths[]) + } + } + +-enum IOFlowType{ ++enum IOFlowType { + IO_SRC = 0, + IO_DST, + IO_FLOW_INVALID, +@@ -784,7 +784,8 @@ static void *IOCopyThread(void *arg) + return NULL; + } + +-int start_vsock_io_copy(const char *exec_id, int sync_fd, bool detach, const char *fifoin, const char *fifoout, const char *fifoerr, ++int start_vsock_io_copy(const char *exec_id, int sync_fd, bool detach, const char *fifoin, const char *fifoout, ++ const char *fifoerr, + int stdin_fd, struct io_write_wrapper *stdout_handler, struct io_write_wrapper *stderr_handler, + const char *vsocks[], pthread_t *tid) + { +diff --git a/src/daemon/modules/service/vsock_io_handler.h b/src/daemon/modules/service/vsock_io_handler.h +index cc0c1dd0..8bda7711 100644 +--- a/src/daemon/modules/service/vsock_io_handler.h ++++ b/src/daemon/modules/service/vsock_io_handler.h +@@ -20,8 +20,7 @@ + #include + + #ifdef __cplusplus +-extern "C" +-{ ++extern "C" { + #endif + + bool is_vsock_path(const char *path); +@@ -35,7 +34,8 @@ int create_daemon_vsockpaths(const char *sandbox_id, uint32_t cid, bool attach_s + + void delete_daemon_vsockpaths(const char *sandbox_id, const char *vsockpaths[]); + +-int start_vsock_io_copy(const char *exec_id, int sync_fd, bool detach, const char *fifoin, const char *fifoout, const char *fifoerr, ++int start_vsock_io_copy(const char *exec_id, int sync_fd, bool detach, const char *fifoin, const char *fifoout, ++ const char *fifoerr, + int stdin_fd, struct io_write_wrapper *stdout_handler, struct io_write_wrapper *stderr_handler, + const char *vsocks[], pthread_t *tid); + +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 +index d6d94461..c6f97da1 100644 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.cc ++++ b/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.cc +@@ -36,7 +36,8 @@ SandboxerAsyncWaitCall::SandboxerAsyncWaitCall(std::shared_ptr bool ++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()); +@@ -96,10 +97,11 @@ SandboxerAsyncWaitStatus SandboxerAsyncWaitCall::HandleResponse() + ControllerExitInfo exitInfo; + SandboxerAsyncWaitStatus waitStatus = SANDBOXER_ASYNC_WAIT_STATUS_ERROR; + +- switch(m_status.error_code()) { ++ 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()); ++ 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 +@@ -128,7 +130,8 @@ SandboxerAsyncWaitStatus SandboxerAsyncWaitCall::HandleResponse() + 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()); ++ ERROR("Sandboxer controller wait request failed, error_code: %d: %s", m_status.error_code(), ++ m_status.error_message().c_str()); + SandboxExitCallback(false, exitInfo); + break; + } +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 +index eb633e99..6e5a6756 100644 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.h ++++ b/src/daemon/sandbox/controller/sandboxer/client/grpc_async_wait_call.h +@@ -49,16 +49,26 @@ public: + 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; } ++ 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_responseReader; + std::unique_ptr m_context; + containerd::services::sandbox::v1::ControllerWaitResponse m_response; + grpc::Status m_status; +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 b5dda0ed..11c2b014 100644 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.cc ++++ b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.cc +@@ -102,14 +102,16 @@ auto SandboxerClient::Create(const std::string &sandboxId, const ControllerCreat + 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()); ++ 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, ++void SandboxerClient::StartResponseToSandboxInfo(const containerd::services::sandbox::v1::ControllerStartResponse ++ &response, + ControllerSandboxInfo &sandboxInfo) + { + sandboxInfo.id = response.sandbox_id(); +@@ -132,7 +134,8 @@ auto SandboxerClient::Start(const std::string &sandboxId, ControllerSandboxInfo + 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()); ++ ERROR("Sandboxer controller start request failed, error_code: %d: %s", status.error_code(), ++ status.error_message().c_str()); + return false; + } + +@@ -174,7 +177,8 @@ auto SandboxerClient::InitPrepareRequest(containerd::services::sandbox::v1::Prep + return true; + } + +-auto SandboxerClient::Prepare(const std::string &sandboxId, const ControllerPrepareParams ¶ms, std::string &bundle, Errors &error) -> bool ++auto SandboxerClient::Prepare(const std::string &sandboxId, const ControllerPrepareParams ¶ms, std::string &bundle, ++ Errors &error) -> bool + { + grpc::ClientContext context; + containerd::services::sandbox::v1::PrepareRequest request; +@@ -189,7 +193,8 @@ auto SandboxerClient::Prepare(const std::string &sandboxId, const ControllerPrep + status = m_stub->Prepare(&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()); ++ ERROR("Sandboxer controller prepare request failed, error_code: %d: %s", status.error_code(), ++ status.error_message().c_str()); + return false; + } + +@@ -199,7 +204,7 @@ auto SandboxerClient::Prepare(const std::string &sandboxId, const ControllerPrep + } + + auto SandboxerClient::Purge(const std::string &sandboxId, const std::string &containerId, +- const std::string &execId, Errors &error) -> bool ++ const std::string &execId, Errors &error) -> bool + { + grpc::ClientContext context; + containerd::services::sandbox::v1::PurgeRequest request; +@@ -214,7 +219,8 @@ auto SandboxerClient::Purge(const std::string &sandboxId, const std::string &con + status = m_stub->Purge(&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()); ++ ERROR("Sandboxer controller purge request failed, error_code: %d: %s", status.error_code(), ++ status.error_message().c_str()); + return false; + } + +@@ -237,7 +243,8 @@ auto SandboxerClient::InitUpdateResourcesRequest(containerd::services::sandbox:: + return true; + } + +-auto SandboxerClient::UpdateResources(const std::string &sandboxId, const ControllerUpdateResourcesParams ¶ms, Errors &error) -> bool ++auto SandboxerClient::UpdateResources(const std::string &sandboxId, const ControllerUpdateResourcesParams ¶ms, ++ Errors &error) -> bool + { + grpc::ClientContext context; + containerd::services::sandbox::v1::UpdateResourcesRequest request; +@@ -245,21 +252,24 @@ auto SandboxerClient::UpdateResources(const std::string &sandboxId, const Contro + grpc::Status status; + + if (!InitUpdateResourcesRequest(request, sandboxId, params)) { +- error.SetError("Failed to init update-resources request for sandboxer update-resources request, sandbox id: " + sandboxId); ++ 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()); ++ ERROR("Sandboxer controller update resources request failed, error_code: %d: %s", status.error_code(), ++ status.error_message().c_str()); + return false; + } + + return true; + } + +-void SandboxerClient::PlatformResponseToPlatformInfo(const containerd::services::sandbox::v1::ControllerPlatformResponse &response, ++void SandboxerClient::PlatformResponseToPlatformInfo(const containerd::services::sandbox::v1::ControllerPlatformResponse ++ &response, + ControllerPlatformInfo &platformInfo) + { + auto &platform = response.platform(); +@@ -268,7 +278,8 @@ void SandboxerClient::PlatformResponseToPlatformInfo(const containerd::services: + platformInfo.variant = platform.variant(); + } + +-auto SandboxerClient::Platform(const std::string &sandboxId, ControllerPlatformInfo &platformInfo, Errors &error) -> bool ++auto SandboxerClient::Platform(const std::string &sandboxId, ControllerPlatformInfo &platformInfo, ++ Errors &error) -> bool + { + grpc::ClientContext context; + containerd::services::sandbox::v1::ControllerPlatformRequest request; +@@ -281,7 +292,8 @@ auto SandboxerClient::Platform(const std::string &sandboxId, ControllerPlatformI + 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()); ++ ERROR("Sandboxer controller platform request failed, error_code: %d: %s", status.error_code(), ++ status.error_message().c_str()); + return false; + } + +@@ -304,14 +316,16 @@ auto SandboxerClient::Stop(const std::string &sandboxId, uint32_t timeoutSecs, E + 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()); ++ 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, ++void SandboxerClient::StatusResponseToSandboxStatus(const containerd::services::sandbox::v1::ControllerStatusResponse ++ &response, + ControllerSandboxStatus &sandboxStatus) + { + sandboxStatus.id = response.sandbox_id(); +@@ -324,7 +338,8 @@ void SandboxerClient::StatusResponseToSandboxStatus(const containerd::services:: + sandboxStatus.extra = response.extra().value(); + } + +-auto SandboxerClient::Status(const std::string &sandboxId, bool verbose, ControllerSandboxStatus &sandboxStatus, Errors &error) -> bool ++auto SandboxerClient::Status(const std::string &sandboxId, bool verbose, ControllerSandboxStatus &sandboxStatus, ++ Errors &error) -> bool + { + grpc::ClientContext context; + containerd::services::sandbox::v1::ControllerStatusRequest request; +@@ -338,7 +353,8 @@ auto SandboxerClient::Status(const std::string &sandboxId, bool verbose, Control + 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()); ++ ERROR("Sandboxer controller status request failed, error_code: %d: %s", status.error_code(), ++ status.error_message().c_str()); + return false; + } + +@@ -360,14 +376,16 @@ auto SandboxerClient::Shutdown(const std::string &sandboxId, Errors &error) -> b + 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()); ++ 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 ++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, " +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 85e1e608..accca16b 100644 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.h ++++ b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_client.h +@@ -48,12 +48,14 @@ 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(const std::string &sandboxId, const ControllerPrepareParams ¶ms, std::string &bundle, ++ Errors &error) -> bool; + + auto Purge(const std::string &sandboxId, const std::string &containerId, + const std::string &execId, Errors &error) -> bool; + +- auto UpdateResources(const std::string &sandboxId, const ControllerUpdateResourcesParams ¶ms, Errors &error) -> bool; ++ auto UpdateResources(const std::string &sandboxId, const ControllerUpdateResourcesParams ¶ms, ++ Errors &error) -> bool; + + auto Stop(const std::string &sandboxId, uint32_t timeoutSecs, Errors &error) -> bool; + +diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.cc b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.cc +index 1417ee40..485a0b23 100644 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.cc ++++ b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.cc +@@ -24,7 +24,7 @@ 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_channel(channel), m_sandboxer(sandboxer), m_teardown(false) + { + m_stub = containerd::services::sandbox::v1::Controller::NewStub(m_channel); + } +@@ -46,7 +46,7 @@ auto SandboxerClientMonitor::Monitor(SandboxerAsyncWaitCall *call) -> bool + } + + // Try to monitor the call, if failed, we should delete it right way +- if (!call->Call(*m_stub ,m_cq)) { ++ 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; +@@ -114,11 +114,11 @@ void SandboxerClientMonitor::WaitForDeferredCall() + // 2. SandboxerAsyncWaitCall *: The call handled by the future + void SandboxerClientMonitor::InvokeDeferredCall(SandboxerAsyncWaitCall *call) + { +- m_futures.push_back(std::async([this, 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); ++ 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)); + +@@ -186,7 +186,7 @@ void SandboxerClientMonitor::CheckCompletedFutures() + // 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, ++ // 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 +diff --git a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.h b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.h +index 32fca934..b5740b44 100644 +--- a/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.h ++++ b/src/daemon/sandbox/controller/sandboxer/client/grpc_sandboxer_monitor.h +@@ -68,7 +68,7 @@ private: + // Vector for holding all the calls for monitoring + std::vector m_calls; + std::mutex m_callsMutex; +- // Use to indicate whether ++ // Use to indicate whether + bool m_teardown; + // Vector for holding all the retry calls + std::vector m_deferredCalls; +diff --git a/src/daemon/sandbox/controller/shim/shim_controller.cc b/src/daemon/sandbox/controller/shim/shim_controller.cc +index baddf1aa..39fcf8ea 100644 +--- a/src/daemon/sandbox/controller/shim/shim_controller.cc ++++ b/src/daemon/sandbox/controller/shim/shim_controller.cc +@@ -247,7 +247,8 @@ auto ShimController::GenerateSandboxCreateContainerRequest(const std::string &sa + return nullptr; + } + +- auto requestWrapper = PackCreateContainerRequest(sandboxId, params, hostConfigWrapper->get(), customConfigWrapper->get(), error); ++ auto requestWrapper = PackCreateContainerRequest(sandboxId, params, hostConfigWrapper->get(), ++ customConfigWrapper->get(), error); + if (requestWrapper == nullptr) { + ERROR("Failed to pack create container request"); + error.SetError("Failed to pack create container request"); +@@ -570,7 +571,7 @@ bool ShimController::UpdateNetworkSettings(const std::string &sandboxId, const s + } + + auto requestWrapper = makeUniquePtrCStructWrapper( +- free_container_update_network_settings_request); ++ free_container_update_network_settings_request); + if (requestWrapper == nullptr) { + ERROR("container update network settings request: Out of memory"); + error.Errorf("container update network settings request: Out of memory"); +@@ -583,7 +584,7 @@ bool ShimController::UpdateNetworkSettings(const std::string &sandboxId, const s + container_update_network_settings_response *response { nullptr }; + int ret = m_cb->container.update_network_settings(request, &response); + auto responseWrapper = makeUniquePtrCStructWrapper( +- response, free_container_update_network_settings_response); ++ response, free_container_update_network_settings_response); + + if (ret != 0) { + if (response != nullptr && response->errmsg != nullptr) { +diff --git a/src/daemon/sandbox/sandbox.cc b/src/daemon/sandbox/sandbox.cc +index c8fd30be..b1832265 100644 +--- a/src/daemon/sandbox/sandbox.cc ++++ b/src/daemon/sandbox/sandbox.cc +@@ -942,7 +942,8 @@ auto Sandbox::ParseSandboxMetadataFile() -> std::unique_ptr>(new CStructWrapper(metadata, free_sandbox_metadata)); ++ return std::unique_ptr>(new CStructWrapper(metadata, ++ free_sandbox_metadata)); + } + + auto Sandbox::isValidMetadata(std::unique_ptr> &metadata) -> bool +diff --git a/src/daemon/sandbox/sandbox_manager.cc b/src/daemon/sandbox/sandbox_manager.cc +index 60ce97d5..d3db4fb4 100644 +--- a/src/daemon/sandbox/sandbox_manager.cc ++++ b/src/daemon/sandbox/sandbox_manager.cc +@@ -60,7 +60,8 @@ auto SandboxManager::Init(Errors &error) -> bool + return true; + } + +-auto SandboxManager::CreateSandbox(const std::string &name, RuntimeInfo &info, std::string &netNsPath, std::string &netMode, ++auto SandboxManager::CreateSandbox(const std::string &name, RuntimeInfo &info, std::string &netNsPath, ++ std::string &netMode, + const runtime::v1::PodSandboxConfig &sandboxConfig, const std::string &image, Errors &error) -> std::shared_ptr + { + std::shared_ptr sandbox; +diff --git a/src/daemon/sandbox/sandbox_manager.h b/src/daemon/sandbox/sandbox_manager.h +index 3a6ce3c9..c9ed78ed 100644 +--- a/src/daemon/sandbox/sandbox_manager.h ++++ b/src/daemon/sandbox/sandbox_manager.h +@@ -37,7 +37,8 @@ public: + + // Create meanningful sandbox instance + auto CreateSandbox(const std::string &name, RuntimeInfo &info, std::string &netNsPath, std::string &netMode, +- const runtime::v1::PodSandboxConfig &sandboxConfig, const std::string &image, Errors &error) -> std::shared_ptr; ++ const runtime::v1::PodSandboxConfig &sandboxConfig, const std::string &image, ++ Errors &error) -> std::shared_ptr; + + auto GetSandbox(const std::string &idOrName) -> std::shared_ptr; + auto DeleteSandbox(const std::string &idOrName, Errors &error) -> bool; +diff --git a/src/daemon/sandbox/sandbox_ops.cc b/src/daemon/sandbox/sandbox_ops.cc +index 2f4a46f6..005063c0 100644 +--- a/src/daemon/sandbox/sandbox_ops.cc ++++ b/src/daemon/sandbox/sandbox_ops.cc +@@ -70,7 +70,7 @@ static int do_sandbox_prepare(const container_config_v2_common_config *config, + } + + params.containerId = config->id; +- params.execId = (nullptr == exec_id) ? "" :exec_id; ++ params.execId = (nullptr == exec_id) ? "" : exec_id; + params.spec = std::move(std::unique_ptr(new std::string(oci_spec))); + + if (generate_ctrl_rootfs(params, config) != 0) { +diff --git a/src/daemon/sandbox/sandbox_ops.h b/src/daemon/sandbox/sandbox_ops.h +index bcb1e9d2..bef884fb 100644 +--- a/src/daemon/sandbox/sandbox_ops.h ++++ b/src/daemon/sandbox/sandbox_ops.h +@@ -21,8 +21,7 @@ + #include + + #ifdef __cplusplus +-extern "C" +-{ ++extern "C" { + #endif + + int sandbox_prepare_container(const container_config_v2_common_config *config, +diff --git a/src/utils/cpputils/url.cc b/src/utils/cpputils/url.cc +index baaded07..c1e5d27f 100644 +--- a/src/utils/cpputils/url.cc ++++ b/src/utils/cpputils/url.cc +@@ -122,8 +122,9 @@ int UnescapeDealWithPercentSign(size_t &i, std::string &s, const EncodeMode &mod + } + // for 3 bit hex, max value is 8 + if (mode == EncodeMode::ENCODE_HOST && s1 < 8 && +- std::string(s.begin() + static_cast(i), s.begin() + static_cast(i+3)) != percentSign) { +- ERROR("invalid URL escape %s", std::string(s.begin() + static_cast(i), s.begin() + static_cast(i + 3)).c_str()); ++ std::string(s.begin() + static_cast(i), s.begin() + static_cast(i + 3)) != percentSign) { ++ ERROR("invalid URL escape %s", std::string(s.begin() + static_cast(i), ++ s.begin() + static_cast(i + 3)).c_str()); + return -1; + } + if (mode == EncodeMode::ENCODE_ZONE) { +diff --git a/src/utils/cutils/error.h b/src/utils/cutils/error.h +index 75eae760..1ad799fa 100644 +--- a/src/utils/cutils/error.h ++++ b/src/utils/cutils/error.h +@@ -47,7 +47,7 @@ extern "C" { + /* info for detach */ \ + XX(INFO_DETACH, "Attach detach") \ + /* err max */ \ +- XX(ERR_UNKNOWN, "Unknown error") ++ XX(ERR_UNKNOWN, "Unknown error") + + #define ISULAD_ERRNO_GEN(n, s) ISULAD_##n, + typedef enum { ISULAD_ERRNO_MAP(ISULAD_ERRNO_GEN) } isulad_errno_t; +diff --git a/src/utils/cutils/map/map.h b/src/utils/cutils/map/map.h +index 45ce26b8..d569a3da 100644 +--- a/src/utils/cutils/map/map.h ++++ b/src/utils/cutils/map/map.h +@@ -20,10 +20,6 @@ + + #include "rb_tree.h" + +-#ifdef __cplusplus +-extern "C" { +-#endif +- + struct _map_t; + + #if defined(__cplusplus) || defined(c_plusplus) +@@ -113,9 +109,5 @@ void map_clear(map_t *map); + } + #endif + +-#ifdef __cplusplus +-} +-#endif +- + #endif // UTILS_CUTILS_MAP_MAP_H + +diff --git a/src/utils/tar/isulad_tar.c b/src/utils/tar/isulad_tar.c +index 2e61d823..bbe4c3b2 100644 +--- a/src/utils/tar/isulad_tar.c ++++ b/src/utils/tar/isulad_tar.c +@@ -97,7 +97,8 @@ cleanup: + return ret; + } + +-static int resolve_host_source_path(const char *path, bool follow_link, char **resolved_path, char **rebase_name, char **err) ++static int resolve_host_source_path(const char *path, bool follow_link, char **resolved_path, char **rebase_name, ++ char **err) + { + int ret = -1; + int nret = 0; +@@ -419,7 +420,8 @@ cleanup: + return ret; + } + +-static int tar_resource_rebase(const char *path, const char *rebase, const char *root_dir, struct io_read_wrapper *archive_reader, char **err) ++static int tar_resource_rebase(const char *path, const char *rebase, const char *root_dir, ++ struct io_read_wrapper *archive_reader, char **err) + { + int ret = -1; + int nret; +@@ -450,7 +452,8 @@ cleanup: + return ret; + } + +-int tar_resource(const struct archive_copy_info *info, const char *root_dir, struct io_read_wrapper *archive_reader, char **err) ++int tar_resource(const struct archive_copy_info *info, const char *root_dir, struct io_read_wrapper *archive_reader, ++ char **err) + { + if (info == NULL || root_dir == NULL || archive_reader == NULL || err == NULL) { + return -1; +diff --git a/src/utils/tar/isulad_tar.h b/src/utils/tar/isulad_tar.h +index 414bb024..401dcf50 100644 +--- a/src/utils/tar/isulad_tar.h ++++ b/src/utils/tar/isulad_tar.h +@@ -43,7 +43,8 @@ struct archive_copy_info *copy_info_source_path(const char *path, bool follow_li + char *prepare_archive_copy(const struct archive_copy_info *srcinfo, const struct archive_copy_info *dstinfo, + char **src_base, char **dst_base, char **err); + +-int tar_resource(const struct archive_copy_info *info, const char *root_dir, struct io_read_wrapper *archive_reader, char **err); ++int tar_resource(const struct archive_copy_info *info, const char *root_dir, struct io_read_wrapper *archive_reader, ++ char **err); + + int archive_copy_to(const struct io_read_wrapper *content, const struct archive_copy_info *srcinfo, + const char *dstpath, const char *root_dir, char **err); +diff --git a/test/cutils/utils_file/utils_file_ut.cc b/test/cutils/utils_file/utils_file_ut.cc +index cacfef45..b3e35744 100644 +--- a/test/cutils/utils_file/utils_file_ut.cc ++++ b/test/cutils/utils_file/utils_file_ut.cc +@@ -200,7 +200,7 @@ TEST(utils_file, test_util_proc_file_line_by_line) + ASSERT_EQ(util_proc_file_line_by_line(fp, nullptr, (void *)checked_layers), -1); + fclose(fp); + ASSERT_EQ(util_path_remove(path.c_str()), 0); +- ++ + ASSERT_EQ(util_proc_file_line_by_line(nullptr, parse_checked_layer_cb, (void *)checked_layers), -1); + } + +diff --git a/test/mocks/callback_mock.cc b/test/mocks/callback_mock.cc +index ef0e347c..153446eb 100644 +--- a/test/mocks/callback_mock.cc ++++ b/test/mocks/callback_mock.cc +@@ -25,7 +25,8 @@ void MockCallback_SetMock(std::shared_ptr mock) + g_container_callback_mock = mock; + } + +-static int service_executor_container_create(const container_create_request *request, container_create_response **response) ++static int service_executor_container_create(const container_create_request *request, ++ container_create_response **response) + { + if (g_container_callback_mock != nullptr) { + return g_container_callback_mock->ContainerCreate(request, response); +@@ -50,7 +51,8 @@ static int service_executor_container_stop(const container_stop_request *request + return 0; + } + +-static int service_executor_container_remove(const container_delete_request *request, container_delete_response **response) ++static int service_executor_container_remove(const container_delete_request *request, ++ container_delete_response **response) + { + if (g_container_callback_mock != nullptr) { + return g_container_callback_mock->ContainerRemove(request, response); +@@ -67,7 +69,7 @@ static int service_executor_container_wait(const container_wait_request *request + } + + static int service_executor_container_update_network_settings(const container_update_network_settings_request *request, +- container_update_network_settings_response **response) ++ container_update_network_settings_response **response) + { + if (g_container_callback_mock != nullptr) { + return g_container_callback_mock->ContainerUpdateNetworkSettings(request, response); +diff --git a/test/mocks/controller_stub_mock.cc b/test/mocks/controller_stub_mock.cc +index eadf3cb4..712540bb 100644 +--- a/test/mocks/controller_stub_mock.cc ++++ b/test/mocks/controller_stub_mock.cc +@@ -2,221 +2,313 @@ + + static std::shared_ptr g_controller_stub_mock = NULL; + +-std::unique_ptr NewDummyControllerStub() { +- std::unique_ptr stub(new DummyControllerStub()); +- return stub; ++std::unique_ptr NewDummyControllerStub() ++{ ++ std::unique_ptr stub(new DummyControllerStub()); ++ return stub; + } + +-void MockControllerStub_SetMock(std::shared_ptr mock) { ++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); ++::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 +index b3920bf8..85cb82bb 100644 +--- a/test/mocks/controller_stub_mock.h ++++ b/test/mocks/controller_stub_mock.h +@@ -23,73 +23,212 @@ + // 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)); ++ 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; ++ ::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; ++ ::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(); +diff --git a/test/mocks/grpc_async_wait_call_mock.cc b/test/mocks/grpc_async_wait_call_mock.cc +index 034cc65c..5eef1794 100644 +--- a/test/mocks/grpc_async_wait_call_mock.cc ++++ b/test/mocks/grpc_async_wait_call_mock.cc +@@ -34,7 +34,8 @@ SandboxerAsyncWaitCall::SandboxerAsyncWaitCall(std::shared_ptr bool ++auto SandboxerAsyncWaitCall::Call(containerd::services::sandbox::v1::Controller::StubInterface &stub, ++ grpc::CompletionQueue &cq) -> bool + { + if (g_sandboxer_async_wait_call_mock == NULL) { + return true; +diff --git a/test/mocks/grpc_async_wait_call_mock.h b/test/mocks/grpc_async_wait_call_mock.h +index eb890ced..c79f998e 100644 +--- a/test/mocks/grpc_async_wait_call_mock.h ++++ b/test/mocks/grpc_async_wait_call_mock.h +@@ -29,7 +29,7 @@ public: + MOCK_METHOD2(SandboxExitCallback, void(bool statusOK, const ControllerExitInfo &exitInfo)); + MOCK_METHOD0(SandboxPendingCallback, void()); + MOCK_METHOD0(SandboxReadyCallback, void()); +- MOCK_METHOD0(GetSandboxId, const std::string &()); ++ MOCK_METHOD0(GetSandboxId, const std::string & ()); + }; + + void MockSandboxerAsyncWaitCall_SetMock(std::shared_ptr mock); +diff --git a/test/mocks/grpc_sandboxer_client_mock.cc b/test/mocks/grpc_sandboxer_client_mock.cc +index 0e57cfe5..03df9048 100644 +--- a/test/mocks/grpc_sandboxer_client_mock.cc ++++ b/test/mocks/grpc_sandboxer_client_mock.cc +@@ -58,7 +58,8 @@ auto SandboxerClient::Start(const std::string &sandboxId, ControllerSandboxInfo + return g_sandboxer_client_mock->Start(sandboxId, sandboxInfo, error); + } + +-auto SandboxerClient::Platform(const std::string &sandboxId, ControllerPlatformInfo &platformInfo, Errors &error) -> bool ++auto SandboxerClient::Platform(const std::string &sandboxId, ControllerPlatformInfo &platformInfo, ++ Errors &error) -> bool + { + if (g_sandboxer_client_mock == NULL) { + return true; +@@ -66,7 +67,8 @@ 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::Prepare(const std::string &sandboxId, const ControllerPrepareParams ¶ms, std::string &bundle, ++ Errors &error) -> bool + { + if (g_sandboxer_client_mock == NULL) { + return true; +@@ -83,7 +85,8 @@ auto SandboxerClient::Purge(const std::string &sandboxId, const std::string &con + return g_sandboxer_client_mock->Purge(sandboxId, containerId, execId, error); + } + +-auto SandboxerClient::UpdateResources(const std::string &sandboxId, const ControllerUpdateResourcesParams ¶ms, Errors &error) -> bool ++auto SandboxerClient::UpdateResources(const std::string &sandboxId, const ControllerUpdateResourcesParams ¶ms, ++ Errors &error) -> bool + { + if (g_sandboxer_client_mock == NULL) { + return true; +@@ -99,7 +102,8 @@ auto SandboxerClient::Stop(const std::string &sandboxId, uint32_t timeoutSecs, E + return g_sandboxer_client_mock->Stop(sandboxId, timeoutSecs, error); + } + +-auto SandboxerClient::Wait(std::shared_ptr cb, const std::string &sandboxId, Errors &error) -> bool ++auto SandboxerClient::Wait(std::shared_ptr cb, const std::string &sandboxId, ++ Errors &error) -> bool + { + if (g_sandboxer_client_mock == NULL) { + return true; +@@ -107,7 +111,8 @@ auto SandboxerClient::Wait(std::shared_ptr cb, const std: + return g_sandboxer_client_mock->Wait(cb, sandboxId, error); + } + +-auto SandboxerClient::Status(const std::string &sandboxId, bool verbose, ControllerSandboxStatus &sandboxStatus, Errors &error) -> bool ++auto SandboxerClient::Status(const std::string &sandboxId, bool verbose, ControllerSandboxStatus &sandboxStatus, ++ Errors &error) -> bool + { + if (g_sandboxer_client_mock == NULL) { + return true; +diff --git a/test/mocks/grpc_sandboxer_client_mock.h b/test/mocks/grpc_sandboxer_client_mock.h +index a3dcd690..ac06462a 100644 +--- a/test/mocks/grpc_sandboxer_client_mock.h ++++ b/test/mocks/grpc_sandboxer_client_mock.h +@@ -28,12 +28,16 @@ public: + 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_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(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, Errors &error)); ++ MOCK_METHOD4(Status, bool(const std::string &sandboxId, bool verbose, ControllerSandboxStatus &sandboxStatus, ++ Errors &error)); + MOCK_METHOD2(Shutdown, bool(const std::string &sandboxId, Errors &error)); + }; + +diff --git a/test/mocks/grpc_sandboxer_monitor_mock.cc b/test/mocks/grpc_sandboxer_monitor_mock.cc +index e307e0ae..b3ddda87 100644 +--- a/test/mocks/grpc_sandboxer_monitor_mock.cc ++++ b/test/mocks/grpc_sandboxer_monitor_mock.cc +@@ -19,7 +19,7 @@ static std::shared_ptr g_sandboxer_client_monitor_mo + + + SandboxerClientMonitor::SandboxerClientMonitor(std::shared_ptr channel, const std::string &sandboxer): +- m_channel(channel), m_sandboxer(sandboxer) ,m_teardown(false) {} ++ m_channel(channel), m_sandboxer(sandboxer), m_teardown(false) {} + + void SandboxerClientMonitor::Start() + { +diff --git a/test/mocks/isulad_config_mock.h b/test/mocks/isulad_config_mock.h +index 6a92fc13..6c6ff7f1 100644 +--- a/test/mocks/isulad_config_mock.h ++++ b/test/mocks/isulad_config_mock.h +@@ -40,7 +40,7 @@ public: + MOCK_METHOD0(InitIsuladDaemonConstants, int (void)); + MOCK_METHOD0(GetIsuladDaemonConstants, isulad_daemon_constants * (void)); + MOCK_METHOD0(ConfGetIsuladUsernsRemap, char *(void)); +- MOCK_METHOD0(ConfGetServerConf, struct service_arguments *(void)); ++ MOCK_METHOD0(ConfGetServerConf, struct service_arguments * (void)); + MOCK_METHOD0(ConfGetSandboxRootPath, char *(void)); + MOCK_METHOD0(ConfGetSandboxStatePath, char *(void)); + }; +diff --git a/test/mocks/sandbox_mock.cc b/test/mocks/sandbox_mock.cc +index e5aefdda..9db57a93 100644 +--- a/test/mocks/sandbox_mock.cc ++++ b/test/mocks/sandbox_mock.cc +@@ -77,7 +77,7 @@ const std::string &Sandbox::GetRuntimeHandle() const + return defaultStr; + } + +-const runtime::v1::PodSandboxConfig & Sandbox::GetSandboxConfig() const ++const runtime::v1::PodSandboxConfig &Sandbox::GetSandboxConfig() const + { + if (g_sandbox_mock != nullptr) { + return g_sandbox_mock->GetSandboxConfig(); +diff --git a/test/mocks/sandbox_mock.h b/test/mocks/sandbox_mock.h +index 341042e9..98f40ad2 100644 +--- a/test/mocks/sandbox_mock.h ++++ b/test/mocks/sandbox_mock.h +@@ -31,7 +31,7 @@ public: + MOCK_METHOD0(GetName, const std::string & ()); + MOCK_METHOD0(GetSandboxer, const std::string & ()); + MOCK_METHOD0(GetRuntimeHandle, const std::string & ()); +- MOCK_METHOD0(GetSandboxConfig, const runtime::v1::PodSandboxConfig &()); ++ MOCK_METHOD0(GetSandboxConfig, const runtime::v1::PodSandboxConfig & ()); + MOCK_METHOD0(GetMutableSandboxConfig, std::shared_ptr()); + MOCK_METHOD0(GetRootDir, const std::string & ()); + MOCK_METHOD0(GetStateDir, std::string & ()); +diff --git a/test/mocks/service_container_api_mock.h b/test/mocks/service_container_api_mock.h +index 350a2fff..9a39f483 100644 +--- a/test/mocks/service_container_api_mock.h ++++ b/test/mocks/service_container_api_mock.h +@@ -23,7 +23,7 @@ + + class MockServiceContainerApi { + public: +- MOCK_METHOD3(InspectContainer, container_inspect *(const char *id, int timeout, bool with_host_config)); ++ MOCK_METHOD3(InspectContainer, container_inspect * (const char *id, int timeout, bool with_host_config)); + }; + + void MockServiceContainerApi_SetMock(std::shared_ptr mock); +diff --git a/test/mocks/shim_controller_mock.cc b/test/mocks/shim_controller_mock.cc +index 88694dbe..e0ffc563 100644 +--- a/test/mocks/shim_controller_mock.cc ++++ b/test/mocks/shim_controller_mock.cc +@@ -117,7 +117,8 @@ bool ShimController::Wait(std::shared_ptr cb, const std:: + return true; + } + +-std::unique_ptr ShimController::Status(const std::string &sandboxId, bool verbose, Errors &error) ++std::unique_ptr ShimController::Status(const std::string &sandboxId, bool verbose, ++ Errors &error) + { + if (g_shim_controller_mock != nullptr) { + return g_shim_controller_mock->Status(sandboxId, verbose, error); +@@ -133,7 +134,8 @@ bool ShimController::Shutdown(const std::string &sandboxId, Errors &error) + return true; + } + +-bool ShimController::UpdateNetworkSettings(const std::string &sandboxId, const std::string &networkSettings, Errors &error) ++bool ShimController::UpdateNetworkSettings(const std::string &sandboxId, const std::string &networkSettings, ++ Errors &error) + { + if (g_shim_controller_mock != nullptr) { + return g_shim_controller_mock->UpdateNetworkSettings(sandboxId, networkSettings, error); +diff --git a/test/mocks/shim_controller_mock.h b/test/mocks/shim_controller_mock.h +index 3be05246..6d0de591 100644 +--- a/test/mocks/shim_controller_mock.h ++++ b/test/mocks/shim_controller_mock.h +@@ -39,15 +39,17 @@ public: + const ControllerPrepareParams ¶ms, + Errors &error)); + MOCK_METHOD4(Purge, bool(const std::string &sandboxId, const std::string &containerId, +- const std::string &execId, Errors &error)); ++ const std::string &execId, Errors &error)); + MOCK_METHOD3(UpdateResources, bool(const std::string &sandboxId, + const ControllerUpdateResourcesParams ¶ms, + 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_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)); ++ MOCK_METHOD3(UpdateNetworkSettings, bool(const std::string &sandboxId, const std::string &networkSettings, ++ Errors &error)); + }; + + void MockShimController_SetMock(std::shared_ptr mock); +diff --git a/test/network/cni_operate/cni_operate_ut.cc b/test/network/cni_operate/cni_operate_ut.cc +index 4194641b..f61fee57 100644 +--- a/test/network/cni_operate/cni_operate_ut.cc ++++ b/test/network/cni_operate/cni_operate_ut.cc +@@ -47,28 +47,28 @@ using namespace std; + + extern "C" { + DECLARE_WRAPPER(cni_cache_read, cni_cached_info *, +- (const char *cache_dir, const char *net_name, const struct runtime_conf *rc)); ++ (const char *cache_dir, const char *net_name, const struct runtime_conf *rc)); + DEFINE_WRAPPER(cni_cache_read, cni_cached_info *, +- (const char *cache_dir, const char *net_name, const struct runtime_conf *rc), +- (cache_dir, net_name, rc)); ++ (const char *cache_dir, const char *net_name, const struct runtime_conf *rc), ++ (cache_dir, net_name, rc)); + +- DECLARE_WRAPPER(cni_check_network_list, int, +- (const struct cni_network_list_conf *list, const struct runtime_conf *rc, struct cni_opt_result **p_result)); ++ DECLARE_WRAPPER(cni_check_network_list, int, ++ (const struct cni_network_list_conf *list, const struct runtime_conf *rc, struct cni_opt_result **p_result)); + DEFINE_WRAPPER(cni_check_network_list, int, +- (const struct cni_network_list_conf *list, const struct runtime_conf *rc, struct cni_opt_result **p_result), +- (list, rc, p_result)); ++ (const struct cni_network_list_conf *list, const struct runtime_conf *rc, struct cni_opt_result **p_result), ++ (list, rc, p_result)); + +- DECLARE_WRAPPER(util_atomic_write_file, int, +- (const char *fname, const char *content, size_t content_len, mode_t mode, bool sync)); ++ DECLARE_WRAPPER(util_atomic_write_file, int, ++ (const char *fname, const char *content, size_t content_len, mode_t mode, bool sync)); + DEFINE_WRAPPER(util_atomic_write_file, int, +- (const char *fname, const char *content, size_t content_len, mode_t mode, bool sync), +- (fname, content, content_len, mode, sync)); +- +- DECLARE_WRAPPER(cni_del_network_list, int, +- (const struct cni_network_list_conf *list, const struct runtime_conf *rc, struct cni_opt_result **p_result)); ++ (const char *fname, const char *content, size_t content_len, mode_t mode, bool sync), ++ (fname, content, content_len, mode, sync)); ++ ++ DECLARE_WRAPPER(cni_del_network_list, int, ++ (const struct cni_network_list_conf *list, const struct runtime_conf *rc, struct cni_opt_result **p_result)); + DEFINE_WRAPPER(cni_del_network_list, int, +- (const struct cni_network_list_conf *list, const struct runtime_conf *rc, struct cni_opt_result **p_result), +- (list, rc, p_result)); ++ (const struct cni_network_list_conf *list, const struct runtime_conf *rc, struct cni_opt_result **p_result), ++ (list, rc, p_result)); + + DECLARE_WRAPPER(calloc, void *, (size_t nmemb, size_t size)); + DEFINE_WRAPPER(calloc, void *, (size_t nmemb, size_t size), (nmemb, size)); +@@ -90,19 +90,19 @@ public: + m_list.bytes = cni_net_conf_list_generate_json(m_list.list, &ctx, &jerr); + m_aliases_array = invoke_network_get_aliases_from_cached_info(m_info); + m_manager = { +- .id = (char *)"827bdd4b0b4e28d24dbaf3c563687ff6ffd23cd8fda38cadf818ac324fe5de3e", ++ .id = (char *)"827bdd4b0b4e28d24dbaf3c563687ff6ffd23cd8fda38cadf818ac324fe5de3e", + .netns_path = (char *)"/var/run/netns/isulacni-7dbc2c7d85279d5a", + .ifname = (char *)"eth0" + }; + m_manager.annotations = map_new(MAP_STR_STR, MAP_DEFAULT_CMP_FUNC, MAP_DEFAULT_FREE_FUNC); +- ++ + ctx = { OPT_PARSE_STRICT, 0 }; + aliases_json = cni_array_of_strings_container_generate_json(m_aliases_array, &ctx, &jerr); + if (aliases_json == nullptr) { + printf("Parse aliases_json failed: %s", jerr); + } + (void)map_replace(m_manager.annotations, (void *)aliases_str, (void *)aliases_json); +- ++ + free(aliases_json); + } + +@@ -140,7 +140,7 @@ TEST_F(CniOperateUnitTest, test_check_network_plane) + MOCK_CLEAR(calloc); + } + +- { ++ { + // cached info will be free in check_network_plane + MOCK_SET(cni_cache_read, invoke_network_get_cached_info((char *)CNI_CACHE_INFO)); + MOCK_SET(cni_check_network_list, 0); +diff --git a/test/network/network_mock.cc b/test/network/network_mock.cc +index 1fa1cc2e..27422b5f 100644 +--- a/test/network/network_mock.cc ++++ b/test/network/network_mock.cc +@@ -64,7 +64,7 @@ cni_array_of_strings_container *invoke_network_get_aliases_from_cached_info(cni_ + aliases_array->items = (char **)isula_smart_calloc_s(sizeof(char *), info->aliases_len); + EXPECT_THAT(aliases_array->items, testing::NotNull()) << "Out of memory" << std::endl; + for (size_t i = 0; i < info->aliases_len; i++) { +- aliases_array->items[i]= util_strdup_s(info->aliases[i]); ++ aliases_array->items[i] = util_strdup_s(info->aliases[i]); + aliases_array->len += 1; + } + +diff --git a/test/sandbox/controller/controller_common.cc b/test/sandbox/controller/controller_common.cc +index ed9c84d7..5f870c34 100644 +--- a/test/sandbox/controller/controller_common.cc ++++ b/test/sandbox/controller/controller_common.cc +@@ -15,7 +15,8 @@ + + #include "controller_common.h" + +-std::unique_ptr CreateTestMountInfo() { ++std::unique_ptr CreateTestMountInfo() ++{ + std::unique_ptr mountInfo(new sandbox::ControllerMountInfo()); + mountInfo->source = "/rootfs"; + mountInfo->destination = "/rootfs"; +@@ -23,7 +24,8 @@ std::unique_ptr CreateTestMountInfo() { + return mountInfo; + } + +-std::unique_ptr CreateTestCreateParams() { ++std::unique_ptr CreateTestCreateParams() ++{ + std::unique_ptr params(new sandbox::ControllerCreateParams()); + params->config = std::make_shared(); + params->netNSPath = "/proc/1/ns/net"; +@@ -31,7 +33,8 @@ std::unique_ptr CreateTestCreateParams() { + return params; + } + +-std::unique_ptr CreateTestStreamInfo() { ++std::unique_ptr CreateTestStreamInfo() ++{ + std::unique_ptr streamInfo(new sandbox::ControllerStreamInfo()); + streamInfo->stdin = "/tmp/stdin"; + streamInfo->stdout = "/tmp/stdout"; +@@ -40,7 +43,8 @@ std::unique_ptr CreateTestStreamInfo() { + return streamInfo; + } + +-std::unique_ptr CreateTestPrepareParams() { ++std::unique_ptr CreateTestPrepareParams() ++{ + std::unique_ptr params(new sandbox::ControllerPrepareParams()); + params->containerId = DUMMY_CONTAINER_ID; + params->execId = DUMMY_EXEC_ID; +@@ -51,7 +55,9 @@ std::unique_ptr CreateTestPrepareParams() { + return params; + } + +-std::unique_ptr CreateTestUpdateResourcesParams(google::protobuf::Map &annotations) { ++std::unique_ptr CreateTestUpdateResourcesParams( ++ google::protobuf::Map &annotations) ++{ + std::unique_ptr resources(new std::string("{cpu: 12}")); + std::unique_ptr params( + new sandbox::ControllerUpdateResourcesParams{DUMMY_SANDBOX_ID, std::move(resources), annotations} +diff --git a/test/sandbox/controller/controller_common.h b/test/sandbox/controller/controller_common.h +index e5a22e34..c01ae83c 100644 +--- a/test/sandbox/controller/controller_common.h ++++ b/test/sandbox/controller/controller_common.h +@@ -33,6 +33,7 @@ std::unique_ptr CreateTestStreamInfo(); + + std::unique_ptr CreateTestPrepareParams(); + +-std::unique_ptr CreateTestUpdateResourcesParams(google::protobuf::Map &annotations); ++std::unique_ptr CreateTestUpdateResourcesParams( ++ google::protobuf::Map &annotations); + + #endif // _ISULAD_TEST_SANDBOX_CONTROLLER_CONTROLLER_COMMON_H +\ No newline at end of file +diff --git a/test/sandbox/controller/manager/controller_manager_ut.cc b/test/sandbox/controller/manager/controller_manager_ut.cc +index 8467fbd4..705baaca 100644 +--- a/test/sandbox/controller/manager/controller_manager_ut.cc ++++ b/test/sandbox/controller/manager/controller_manager_ut.cc +@@ -33,11 +33,13 @@ public: + + class ControllerManagerTest : public testing::Test { + protected: +- void SetUp() override { ++ void SetUp() override ++ { + MockIsuladConf_SetMock(isuladConfMock.get()); + } + +- void TearDown() override { ++ void TearDown() override ++ { + MockIsuladConf_SetMock(nullptr); + static_cast(ControllerManagerWrapper::GetInstance())->Clear(); + } +@@ -45,7 +47,8 @@ protected: + std::unique_ptr isuladConfMock = std::unique_ptr(new MockIsuladConf()); + }; + +-static struct service_arguments *CreateDummyServerConf(const std::string &conf) { ++static struct service_arguments *CreateDummyServerConf(const std::string &conf) ++{ + parser_error err = nullptr; + struct service_arguments *args = (struct service_arguments *)util_common_calloc_s(sizeof(struct service_arguments)); + if (args == nullptr) { +@@ -59,7 +62,8 @@ static struct service_arguments *CreateDummyServerConf(const std::string &conf) + return args; + } + +-static void FreeDummyServerconf(struct service_arguments *args) { ++static void FreeDummyServerconf(struct service_arguments *args) ++{ + if (args != nullptr) { + free_isulad_daemon_configs(args->json_confs); + free(args); +@@ -70,7 +74,8 @@ static void FreeDummyServerconf(struct service_arguments *args) { + TEST_F(ControllerManagerTest, InitTestSucceed) + { + Errors err; +- const std::string daemonConfig = "{\"cri-sandboxers\": {\"kuasar\": {\"name\": \"vmm\",\"address\": \"/run/vmm-sandboxer.sock\"}}}"; ++ const std::string daemonConfig = ++ "{\"cri-sandboxers\": {\"kuasar\": {\"name\": \"vmm\",\"address\": \"/run/vmm-sandboxer.sock\"}}}"; + struct service_arguments *args = CreateDummyServerConf(daemonConfig); + ASSERT_NE(args, nullptr); + EXPECT_CALL(*isuladConfMock, ConfGetServerConf()).Times(1).WillOnce(testing::Return(args)); +@@ -130,7 +135,8 @@ TEST_F(ControllerManagerTest, InitTestSucceedWithNullConfig) + TEST_F(ControllerManagerTest, InitTestFailedWithDupShimConfig) + { + Errors err; +- const std::string daemonConfig = "{\"cri-sandboxers\": {\"kuasar\": {\"name\": \"shim\",\"address\": \"/run/vmm-sandboxer.sock\"}}}"; ++ const std::string daemonConfig = ++ "{\"cri-sandboxers\": {\"kuasar\": {\"name\": \"shim\",\"address\": \"/run/vmm-sandboxer.sock\"}}}"; + struct service_arguments *args = CreateDummyServerConf(daemonConfig); + ASSERT_NE(args, nullptr); + EXPECT_CALL(*isuladConfMock, ConfGetServerConf()).Times(1).WillOnce(testing::Return(args)); +@@ -148,7 +154,8 @@ TEST_F(ControllerManagerTest, InitTestFailedWithDupShimConfig) + TEST_F(ControllerManagerTest, InitTestFailedWithDupKuasarConfig) + { + Errors err; +- const std::string daemonConfig = "{\"cri-sandboxers\": {\"kuasar\": {\"name\": \"vmm1\",\"address\": \"/run/vmm1-sandboxer.sock\"},\"kuasar\": {\"name\": \"vmm2\",\"address\": \"/run/vmm2-sandboxer.sock\"}}}"; ++ const std::string daemonConfig = ++ "{\"cri-sandboxers\": {\"kuasar\": {\"name\": \"vmm1\",\"address\": \"/run/vmm1-sandboxer.sock\"},\"kuasar\": {\"name\": \"vmm2\",\"address\": \"/run/vmm2-sandboxer.sock\"}}}"; + struct service_arguments *args = CreateDummyServerConf(daemonConfig); + ASSERT_NE(args, nullptr); + EXPECT_CALL(*isuladConfMock, ConfGetServerConf()).Times(1).WillOnce(testing::Return(args)); +@@ -162,7 +169,8 @@ TEST_F(ControllerManagerTest, InitTestFailedWithDupKuasarConfig) + TEST_F(ControllerManagerTest, InitTestFailedWithDupNameConfig) + { + Errors err; +- const std::string daemonConfig = "{\"cri-sandboxers\": {\"kuasar1\": {\"name\": \"vmm\",\"address\": \"/run/vmm1-sandboxer.sock\"},\"kuasar2\": {\"name\": \"vmm\",\"address\": \"/run/vmm2-sandboxer.sock\"}}}"; ++ const std::string daemonConfig = ++ "{\"cri-sandboxers\": {\"kuasar1\": {\"name\": \"vmm\",\"address\": \"/run/vmm1-sandboxer.sock\"},\"kuasar2\": {\"name\": \"vmm\",\"address\": \"/run/vmm2-sandboxer.sock\"}}}"; + struct service_arguments *args = CreateDummyServerConf(daemonConfig); + ASSERT_NE(args, nullptr); + EXPECT_CALL(*isuladConfMock, ConfGetServerConf()).Times(1).WillOnce(testing::Return(args)); +@@ -176,7 +184,8 @@ TEST_F(ControllerManagerTest, InitTestFailedWithDupNameConfig) + TEST_F(ControllerManagerTest, InitTestFailedWithDupInit) + { + Errors err; +- const std::string daemonConfig = "{\"cri-sandboxers\": {\"kuasar\": {\"name\": \"vmm\",\"address\": \"/run/vmm-sandboxer.sock\"}}}"; ++ const std::string daemonConfig = ++ "{\"cri-sandboxers\": {\"kuasar\": {\"name\": \"vmm\",\"address\": \"/run/vmm-sandboxer.sock\"}}}"; + struct service_arguments *args = CreateDummyServerConf(daemonConfig); + ASSERT_NE(args, nullptr); + EXPECT_CALL(*isuladConfMock, ConfGetServerConf()).Times(2).WillRepeatedly(testing::Return(args)); +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 +index 0596771a..1a58344c 100644 +--- 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 +@@ -35,17 +35,20 @@ public: + + class AsyncWaitCallTest : public testing::Test { + protected: +- void SetUp() override { ++ 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_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 { ++ void TearDown() override ++ { + MockControllerStub_SetMock(nullptr); + } + +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 +index 3a12d042..7e98d844 100644 +--- a/test/sandbox/controller/sandboxer/async_wait_call/dummy_monitor_utils.h ++++ b/test/sandbox/controller/sandboxer/async_wait_call/dummy_monitor_utils.h +@@ -21,7 +21,8 @@ + + #include "controller.h" + +-class DummyClientAsyncResponseReader: public grpc::ClientAsyncResponseReaderInterface { ++class DummyClientAsyncResponseReader: public ++ grpc::ClientAsyncResponseReaderInterface { + public: + DummyClientAsyncResponseReader() = default; + ~DummyClientAsyncResponseReader() = default; +@@ -30,26 +31,32 @@ public: + + void ReadInitialMetadata(void *tag) override {} + +- void Finish(containerd::services::sandbox::v1::ControllerWaitResponse *response, grpc::Status *status, 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) { ++ void SetExitAt(const google::protobuf::Timestamp &exitAt) ++ { + m_exitedAt = exitAt; + } + +- void SetExitStatus(uint32_t status) { ++ void SetExitStatus(uint32_t status) ++ { + m_exitStatus = status; + } + +- void SetStatus(grpc::Status status) { ++ void SetStatus(grpc::Status status) ++ { + m_status = status; + } + +- void *GetTag() { ++ void *GetTag() ++ { + return m_tag; + } + +@@ -70,28 +77,39 @@ enum AsyncWaitCallStatus { + + class DummyCallback: public sandbox::SandboxStatusCallback { + public: +- DummyCallback() { ++ 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 { ++ 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() { ++ AsyncWaitCallStatus GetStatus() ++ { + return m_status; + } + +- uint32_t GetExitStatus() { ++ uint32_t GetExitStatus() ++ { + return m_exitStatus; + } + +- uint64_t GetExitedAt() { ++ uint64_t GetExitedAt() ++ { + return m_exitedAt; + } + private: +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 0804b38b..b0f4758f 100644 +--- a/test/sandbox/controller/sandboxer/sandboxer_client/sandboxer_client_ut.cc ++++ b/test/sandbox/controller/sandboxer/sandboxer_client/sandboxer_client_ut.cc +@@ -21,7 +21,8 @@ + + class SandboxerClientWrapper : public sandbox::SandboxerClient { + public: +- SandboxerClientWrapper(const std::string &sandboxer, const std::string &address) : SandboxerClient(sandboxer, address) { ++ SandboxerClientWrapper(const std::string &sandboxer, const std::string &address) : SandboxerClient(sandboxer, address) ++ { + m_stub = NewDummyControllerStub(); + } + +@@ -30,7 +31,8 @@ public: + + class ControllerSandboxerClientTest : public testing::Test { + protected: +- void SetUp() override { ++ void SetUp() override ++ { + m_sandboxer = "sandboxer"; + m_address = "/tmp/sandboxer.sock"; + +@@ -39,7 +41,8 @@ protected: + MockControllerStub_SetMock(m_stub); + } + +- void TearDown() override { ++ void TearDown() override ++ { + MockControllerStub_SetMock(nullptr); + } + +@@ -50,18 +53,21 @@ protected: + std::shared_ptr m_sandboxerClient; + }; + +-static std::unique_ptr CreateTestGrpcStartResponse() { +- std::unique_ptr response(new containerd::services::sandbox::v1::ControllerStartResponse()); ++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_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() { ++static std::unique_ptr CreateTestPlatformResponse() ++{ + std::unique_ptr response( + new containerd::services::sandbox::v1::ControllerPlatformResponse() + ); +@@ -72,7 +78,8 @@ static std::unique_ptr CreateTestStatusResponse() { ++static std::unique_ptr CreateTestStatusResponse() ++{ + std::unique_ptr response( + new containerd::services::sandbox::v1::ControllerStatusResponse() + ); +@@ -80,29 +87,32 @@ static std::unique_ptrset_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_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) { ++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))); ++ EXPECT_CALL(*m_stub, Create).Times(1).WillOnce(testing::DoAll(testing::SetArgPointee<2>(response), ++ testing::Return(grpc::Status::OK))); + EXPECT_TRUE(m_sandboxerClient->Create(DUMMY_SANDBOX_ID, *params, err)); + EXPECT_TRUE(err.Empty()); + } + +-TEST_F(ControllerSandboxerClientTest, CreateTestNullConfig) { ++TEST_F(ControllerSandboxerClientTest, CreateTestNullConfig) ++{ + Errors err; + std::unique_ptr params(new sandbox::ControllerCreateParams()); + params->config = nullptr; +@@ -113,20 +123,23 @@ TEST_F(ControllerSandboxerClientTest, CreateTestNullConfig) { + EXPECT_THAT(err.GetCMessage(), testing::HasSubstr("Failed to init create request for sandboxer create request")); + } + +-TEST_F(ControllerSandboxerClientTest, CreateTestNullMount) { ++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_stub, Create).Times(1).WillOnce(testing::DoAll(testing::SaveArg<1>(&request), ++ testing::Return(grpc::Status::OK))); + 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()); + } + +-TEST_F(ControllerSandboxerClientTest, CreateTestStatusNotOK) { ++TEST_F(ControllerSandboxerClientTest, CreateTestStatusNotOK) ++{ + Errors err; + std::unique_ptr params = CreateTestCreateParams(); + // Fake a grpc create response. +@@ -138,11 +151,13 @@ TEST_F(ControllerSandboxerClientTest, CreateTestStatusNotOK) { + } + + /************* Unit tests for Start *************/ +-TEST_F(ControllerSandboxerClientTest, StartTestSucceed) { ++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_stub, Start).Times(1).WillOnce(testing::DoAll(testing::SetArgPointee<2>(*response), ++ testing::Return(grpc::Status::OK))); + EXPECT_TRUE(m_sandboxerClient->Start(DUMMY_SANDBOX_ID, sandboxInfo, err)); + EXPECT_TRUE(err.Empty()); + EXPECT_EQ(sandboxInfo.id, DUMMY_SANDBOX_ID); +@@ -152,7 +167,8 @@ TEST_F(ControllerSandboxerClientTest, StartTestSucceed) { + EXPECT_EQ(sandboxInfo.labels["label1"], "value1"); + } + +-TEST_F(ControllerSandboxerClientTest, StartTestStatusNotOK) { ++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"))); +@@ -161,7 +177,8 @@ TEST_F(ControllerSandboxerClientTest, StartTestStatusNotOK) { + } + + /************* Unit tests for Prepare *************/ +-TEST_F(ControllerSandboxerClientTest, PrepareTestSucceed) { ++TEST_F(ControllerSandboxerClientTest, PrepareTestSucceed) ++{ + Errors err; + std::string bundle; + std::unique_ptr params = CreateTestPrepareParams(); +@@ -169,13 +186,15 @@ TEST_F(ControllerSandboxerClientTest, PrepareTestSucceed) { + 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_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) { ++TEST_F(ControllerSandboxerClientTest, PrepareTestNullSpec) ++{ + Errors err; + std::string bundle; + std::unique_ptr params = CreateTestPrepareParams(); +@@ -186,21 +205,24 @@ TEST_F(ControllerSandboxerClientTest, PrepareTestNullSpec) { + EXPECT_THAT(err.GetCMessage(), testing::HasSubstr("Failed to init prepare request for sandboxer prepare request")); + } + +-TEST_F(ControllerSandboxerClientTest, PrepareTestNullMount) { ++TEST_F(ControllerSandboxerClientTest, PrepareTestNullMount) ++{ + 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_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); + EXPECT_TRUE(err.Empty()); + } + +-TEST_F(ControllerSandboxerClientTest, PrepareTestStatusNotOK) { ++TEST_F(ControllerSandboxerClientTest, PrepareTestStatusNotOK) ++{ + Errors err; + std::string bundle; + std::unique_ptr params = CreateTestPrepareParams(); +@@ -210,7 +232,8 @@ TEST_F(ControllerSandboxerClientTest, PrepareTestStatusNotOK) { + } + + /************* Unit tests for Purge *************/ +-TEST_F(ControllerSandboxerClientTest, PurgeTestSucceed) { ++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)); +@@ -218,7 +241,8 @@ TEST_F(ControllerSandboxerClientTest, PurgeTestSucceed) { + EXPECT_TRUE(err.Empty()); + } + +-TEST_F(ControllerSandboxerClientTest, PurgeTestStatusNotOK) { ++TEST_F(ControllerSandboxerClientTest, PurgeTestStatusNotOK) ++{ + 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)); +@@ -226,7 +250,8 @@ TEST_F(ControllerSandboxerClientTest, PurgeTestStatusNotOK) { + } + + /************* Unit tests for UpdateResources *************/ +-TEST_F(ControllerSandboxerClientTest, UpdateResourcesTestSucceed) { ++TEST_F(ControllerSandboxerClientTest, UpdateResourcesTestSucceed) ++{ + Errors err; + google::protobuf::Map annotations; + std::unique_ptr params = CreateTestUpdateResourcesParams(annotations); +@@ -236,7 +261,8 @@ TEST_F(ControllerSandboxerClientTest, UpdateResourcesTestSucceed) { + EXPECT_TRUE(err.Empty()); + } + +-TEST_F(ControllerSandboxerClientTest, UpdateResourcesTestNullResources) { ++TEST_F(ControllerSandboxerClientTest, UpdateResourcesTestNullResources) ++{ + Errors err; + google::protobuf::Map annotations; + std::unique_ptr params = CreateTestUpdateResourcesParams(annotations); +@@ -244,24 +270,29 @@ TEST_F(ControllerSandboxerClientTest, UpdateResourcesTestNullResources) { + // 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")); ++ EXPECT_THAT(err.GetCMessage(), ++ testing::HasSubstr("Failed to init update-resources request for sandboxer update-resources request")); + } + +-TEST_F(ControllerSandboxerClientTest, UpdateResourcesTestStatusNotOK) { ++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_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")); + } + + /************* Unit tests for Platform *************/ +-TEST_F(ControllerSandboxerClientTest, PlatformTestSucceed) { ++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_stub, Platform).Times(1).WillOnce(testing::DoAll(testing::SetArgPointee<2>(*response), ++ testing::Return(grpc::Status::OK))); + EXPECT_TRUE(m_sandboxerClient->Platform(DUMMY_SANDBOX_ID, platformInfo, err)); + EXPECT_TRUE(err.Empty()); + EXPECT_EQ(platformInfo.os, "linux"); +@@ -269,16 +300,19 @@ TEST_F(ControllerSandboxerClientTest, PlatformTestSucceed) { + EXPECT_EQ(platformInfo.variant, "ubuntu"); + } + +-TEST_F(ControllerSandboxerClientTest, PlatformTestStatusNotOK) { ++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_stub, Platform).Times(1).WillOnce(testing::Return(grpc::Status(grpc::StatusCode::ABORTED, ++ "gRPC Abort"))); + 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) { ++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)); +@@ -286,7 +320,8 @@ TEST_F(ControllerSandboxerClientTest, StopTestSucceed) { + EXPECT_TRUE(err.Empty()); + } + +-TEST_F(ControllerSandboxerClientTest, StopTestStatusNotOK) { ++TEST_F(ControllerSandboxerClientTest, StopTestStatusNotOK) ++{ + Errors err; + EXPECT_CALL(*m_stub, Stop).Times(1).WillOnce(testing::Return(grpc::Status(grpc::StatusCode::ABORTED, "gRPC Abort"))); + EXPECT_FALSE(m_sandboxerClient->Stop(DUMMY_SANDBOX_ID, 0, err)); +@@ -294,11 +329,13 @@ TEST_F(ControllerSandboxerClientTest, StopTestStatusNotOK) { + } + + /************* Unit tests for Status *************/ +-TEST_F(ControllerSandboxerClientTest, StatusTestSucceed) { ++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_stub, Status).Times(1).WillOnce(testing::DoAll(testing::SetArgPointee<2>(*response), ++ testing::Return(grpc::Status::OK))); + EXPECT_TRUE(m_sandboxerClient->Status(DUMMY_SANDBOX_ID, false, sandboxStatus, err)); + EXPECT_TRUE(err.Empty()); + EXPECT_EQ(sandboxStatus.id, DUMMY_SANDBOX_ID); +@@ -312,7 +349,8 @@ TEST_F(ControllerSandboxerClientTest, StatusTestSucceed) { + EXPECT_EQ(sandboxStatus.extra, "{extra: test}"); + } + +-TEST_F(ControllerSandboxerClientTest, StatusTestStatusNotOK) { ++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"))); +@@ -321,7 +359,8 @@ TEST_F(ControllerSandboxerClientTest, StatusTestStatusNotOK) { + } + + /************* Unit tests for Shutdown *************/ +-TEST_F(ControllerSandboxerClientTest, ShutdownTestSucceed) { ++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)); +@@ -329,9 +368,11 @@ TEST_F(ControllerSandboxerClientTest, ShutdownTestSucceed) { + EXPECT_TRUE(err.Empty()); + } + +-TEST_F(ControllerSandboxerClientTest, ShutdownTestStatusNotOK) { ++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_stub, Shutdown).Times(1).WillOnce(testing::Return(grpc::Status(grpc::StatusCode::ABORTED, ++ "gRPC Abort"))); + 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/sandboxer_controller_ut.cc b/test/sandbox/controller/sandboxer/sandboxer_controller/sandboxer_controller_ut.cc +index 52c3f28a..f49d7cc5 100644 +--- a/test/sandbox/controller/sandboxer/sandboxer_controller/sandboxer_controller_ut.cc ++++ b/test/sandbox/controller/sandboxer/sandboxer_controller/sandboxer_controller_ut.cc +@@ -21,7 +21,8 @@ + + class SandboxerControllerTest : public testing::Test { + protected: +- void SetUp() override { ++ void SetUp() override ++ { + Errors err; + m_contoller = std::move(std::unique_ptr(new SandboxerController(m_sandboxer, m_address))); + m_sandboxerClientMock = std::make_shared(); +@@ -30,7 +31,8 @@ protected: + m_contoller->Init(err); + } + +- void TearDown() override { ++ void TearDown() override ++ { + m_contoller.reset(nullptr); + } + +@@ -74,7 +76,8 @@ TEST_F(SandboxerControllerTest, StartTestSucceed) + Errors err; + std::unique_ptr sandboxInfo = CreateTestSandboxInfo(); + // Set response to return sandbox_id, and return OK for stub_->Start(). +- EXPECT_CALL(*m_sandboxerClientMock, Start).Times(1).WillOnce(testing::DoAll(testing::SetArgReferee<1>(*sandboxInfo), testing::Return(true))); ++ EXPECT_CALL(*m_sandboxerClientMock, Start).Times(1).WillOnce(testing::DoAll(testing::SetArgReferee<1>(*sandboxInfo), ++ testing::Return(true))); + std::unique_ptr ret = m_contoller->Start(DUMMY_SANDBOX_ID, err); + EXPECT_EQ(ret->id, DUMMY_SANDBOX_ID); + EXPECT_EQ(ret->pid, 1234); +@@ -99,7 +102,8 @@ TEST_F(SandboxerControllerTest, PlatformTestSucceed) + platformInfo->arch = "amd64"; + platformInfo->variant = "openEuler"; + // Set response to return sandbox_id, and return OK for stub_->Platform(). +- EXPECT_CALL(*m_sandboxerClientMock, Platform).Times(1).WillOnce(testing::DoAll(testing::SetArgReferee<1>(*platformInfo), testing::Return(true))); ++ EXPECT_CALL(*m_sandboxerClientMock, Platform).Times(1).WillOnce(testing::DoAll(testing::SetArgReferee<1>(*platformInfo), ++ testing::Return(true))); + std::unique_ptr ret = m_contoller->Platform(DUMMY_SANDBOX_ID, err); + EXPECT_EQ(ret->os, "linux"); + EXPECT_EQ(ret->arch, "amd64"); +@@ -121,7 +125,8 @@ TEST_F(SandboxerControllerTest, PrepareTestSucceed) + 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))); ++ 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); + } +@@ -201,7 +206,8 @@ TEST_F(SandboxerControllerTest, StatusTestSucceed) + sandboxStatus->info["test"] = "test"; + sandboxStatus->exitedAt = DUMMY_EXITED_AT; + // Set response to return sandbox_id, and return OK for stub_->Status(). +- EXPECT_CALL(*m_sandboxerClientMock, Status).Times(1).WillOnce(testing::DoAll(testing::SetArgReferee<2>(*sandboxStatus), testing::Return(true))); ++ EXPECT_CALL(*m_sandboxerClientMock, Status).Times(1).WillOnce(testing::DoAll(testing::SetArgReferee<2>(*sandboxStatus), ++ testing::Return(true))); + std::unique_ptr ret = m_contoller->Status(DUMMY_SANDBOX_ID, false, err); + EXPECT_EQ(ret->id, DUMMY_SANDBOX_ID); + EXPECT_EQ(ret->state, "created"); +diff --git a/test/sandbox/controller/shim/shim_controller_ut.cc b/test/sandbox/controller/shim/shim_controller_ut.cc +index 978e2c36..e43cc645 100644 +--- a/test/sandbox/controller/shim/shim_controller_ut.cc ++++ b/test/sandbox/controller/shim/shim_controller_ut.cc +@@ -24,7 +24,8 @@ + + class ShimControllerTest : public testing::Test { + protected: +- void SetUp() override { ++ void SetUp() override ++ { + Errors err; + m_contoller = std::move(std::unique_ptr(new sandbox::ShimController(m_sandboxer))); + m_containerCallbackMock = std::make_shared(); +@@ -37,7 +38,8 @@ protected: + service_callback_init(); + } + +- void TearDown() override { ++ void TearDown() override ++ { + m_contoller.reset(nullptr); + } + +-- +2.42.0 + diff --git a/0029-2255-Fix-cpusets-offline-issue.patch b/0029-2255-Fix-cpusets-offline-issue.patch new file mode 100644 index 0000000..92f7b63 --- /dev/null +++ b/0029-2255-Fix-cpusets-offline-issue.patch @@ -0,0 +1,445 @@ +From a6f1ff360dded79ce5139a8b97a51c37d2fbd403 Mon Sep 17 00:00:00 2001 +From: xuxuepeng +Date: Thu, 23 Nov 2023 13:18:13 +0000 +Subject: [PATCH 29/64] !2255 Fix cpusets offline issue * Fix cpusets offline + issue + +--- + src/daemon/common/sysinfo.c | 1 + + src/daemon/common/sysinfo.h | 3 + + src/daemon/modules/spec/verify.c | 24 ++--- + test/mocks/image_mock.cc | 16 +++ + test/mocks/image_mock.h | 2 + + test/specs/CMakeLists.txt | 1 + + test/specs/verify/CMakeLists.txt | 85 +++++++++++++++ + test/specs/verify/verify_ut.cc | 173 +++++++++++++++++++++++++++++++ + 8 files changed, 289 insertions(+), 16 deletions(-) + create mode 100644 test/specs/verify/CMakeLists.txt + create mode 100644 test/specs/verify/verify_ut.cc + +diff --git a/src/daemon/common/sysinfo.c b/src/daemon/common/sysinfo.c +index 957b370b..39338925 100644 +--- a/src/daemon/common/sysinfo.c ++++ b/src/daemon/common/sysinfo.c +@@ -393,6 +393,7 @@ sysinfo_t *get_sys_info(bool quiet) + } + + sysinfo->ncpus = get_nprocs(); ++ sysinfo->ncpus_conf = get_nprocs_conf(); + + cgroup_version = common_get_cgroup_version(); + if (cgroup_version < 0) { +diff --git a/src/daemon/common/sysinfo.h b/src/daemon/common/sysinfo.h +index 4ac65df6..363576a9 100644 +--- a/src/daemon/common/sysinfo.h ++++ b/src/daemon/common/sysinfo.h +@@ -25,7 +25,10 @@ extern "C" { + #include "cgroup.h" + + typedef struct { ++ // Number of processors currently online (i.e., available). + int ncpus; ++ // Number of processors configured. ++ int ncpus_conf; + cgroup_mem_info_t cgmeminfo; + cgroup_cpu_info_t cgcpuinfo; + cgroup_hugetlb_info_t hugetlbinfo; +diff --git a/src/daemon/modules/spec/verify.c b/src/daemon/modules/spec/verify.c +index 850595ed..2a8b3259 100644 +--- a/src/daemon/modules/spec/verify.c ++++ b/src/daemon/modules/spec/verify.c +@@ -25,6 +25,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -560,7 +561,7 @@ static bool check_cpu(const char *provided, const char *available) + } + + /* parse unit list */ +-int parse_unit_list(const char *val, bool *available_list, int cpu_num) ++STATIC int parse_unit_list(const char *val, bool *available_list, int cpu_num) + { + int ret = -1; + char *str = NULL; +@@ -612,22 +613,13 @@ out: + } + + /* is cpuset list available */ +-static bool is_cpuset_list_available(const char *provided, const char *available) ++STATIC bool is_cpuset_list_available(const char *provided, const char *available, int cpu_num) + { +- int cpu_num = 0; + int i = 0; + bool ret = false; + bool *parsed_provided = NULL; + bool *parsed_available = NULL; +- sysinfo_t *sysinfo = NULL; +- +- sysinfo = get_sys_info(true); +- if (sysinfo == NULL) { +- ERROR("get sysinfo failed"); +- return false; +- } + +- cpu_num = sysinfo->ncpus; + parsed_provided = util_smart_calloc_s(sizeof(bool), (unsigned int)cpu_num); + if (parsed_provided == NULL) { + ERROR("memory alloc failed!"); +@@ -661,10 +653,10 @@ out: + } + + /* is cpuset cpus available */ +-bool is_cpuset_cpus_available(const sysinfo_t *sysinfo, const char *cpus) ++STATIC bool is_cpuset_cpus_available(const sysinfo_t *sysinfo, const char *cpus) + { + bool ret = false; +- ret = is_cpuset_list_available(cpus, sysinfo->cpusetinfo.cpus); ++ ret = is_cpuset_list_available(cpus, sysinfo->cpusetinfo.cpus, sysinfo->ncpus_conf); + if (!ret) { + ERROR("Checking cpuset.cpus got invalid format: %s.", cpus); + isulad_set_error_message("Checking cpuset.cpus got invalid format: %s.", cpus); +@@ -673,10 +665,10 @@ bool is_cpuset_cpus_available(const sysinfo_t *sysinfo, const char *cpus) + } + + /* is cpuset mems available */ +-bool is_cpuset_mems_available(const sysinfo_t *sysinfo, const char *mems) ++STATIC bool is_cpuset_mems_available(const sysinfo_t *sysinfo, const char *mems) + { + bool ret = false; +- ret = is_cpuset_list_available(mems, sysinfo->cpusetinfo.mems); ++ ret = is_cpuset_list_available(mems, sysinfo->cpusetinfo.mems, sysinfo->ncpus_conf); + if (!ret) { + ERROR("Checking cpuset.mems got invalid format: %s.", mems); + isulad_set_error_message("Checking cpuset.mems got invalid format: %s.", mems); +@@ -685,7 +677,7 @@ bool is_cpuset_mems_available(const sysinfo_t *sysinfo, const char *mems) + } + + // cpuset subsystem checks and adjustments +-static int verify_resources_cpuset(const sysinfo_t *sysinfo, const char *cpus, const char *mems) ++STATIC int verify_resources_cpuset(const sysinfo_t *sysinfo, const char *cpus, const char *mems) + { + int ret = 0; + bool cpus_available = false; +diff --git a/test/mocks/image_mock.cc b/test/mocks/image_mock.cc +index 7114080c..cebe418d 100644 +--- a/test/mocks/image_mock.cc ++++ b/test/mocks/image_mock.cc +@@ -54,3 +54,19 @@ int im_umount_container_rootfs(const char *image_type, const char *image_name, c + } + return 0; + } ++ ++struct graphdriver_status *im_graphdriver_get_status(void) ++{ ++ if (g_image_mock != nullptr) { ++ return g_image_mock->ImGraphdriverGetStatus(); ++ } ++ return nullptr; ++} ++ ++void im_free_graphdriver_status(struct graphdriver_status *status) ++{ ++ if (g_image_mock != nullptr) { ++ g_image_mock->ImFreeGraphdriverStatus(status); ++ } ++ return; ++} +diff --git a/test/mocks/image_mock.h b/test/mocks/image_mock.h +index 0c7c1e51..f05be516 100644 +--- a/test/mocks/image_mock.h ++++ b/test/mocks/image_mock.h +@@ -28,6 +28,8 @@ public: + const char *container_id)); + MOCK_METHOD3(ImUmountContainerRootfs, int(const char *image_type, const char *image_name, + const char *container_id)); ++ MOCK_METHOD0(ImGraphdriverGetStatus, struct graphdriver_status *()); ++ MOCK_METHOD1(ImFreeGraphdriverStatus, void(struct graphdriver_status *status)); + }; + + void MockImage_SetMock(MockImage *mock); +diff --git a/test/specs/CMakeLists.txt b/test/specs/CMakeLists.txt +index 7acd68a1..bf5ed535 100644 +--- a/test/specs/CMakeLists.txt ++++ b/test/specs/CMakeLists.txt +@@ -2,3 +2,4 @@ project(iSulad_UT) + + add_subdirectory(specs) + add_subdirectory(specs_extend) ++add_subdirectory(verify) +diff --git a/test/specs/verify/CMakeLists.txt b/test/specs/verify/CMakeLists.txt +new file mode 100644 +index 00000000..0e60a39e +--- /dev/null ++++ b/test/specs/verify/CMakeLists.txt +@@ -0,0 +1,85 @@ ++project(iSulad_UT) ++ ++SET(EXE specs_verify_ut) ++ ++add_definitions(-DUNIT_TEST=ON) ++ ++add_executable(${EXE} ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_regex.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_verify.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_array.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_string.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_convert.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_file.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_timestamp.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/util_atomic.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_mount_spec.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_fs.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/utils_cap.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/sha256/sha256.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/path.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/map/map.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/map/rb_tree.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/common/err_msg.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/common/sysinfo.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/common/cgroup.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/common/cgroup_v1.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/modules/spec/verify.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/image/oci/oci_ut_common.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/containers_store_mock.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/namespace_mock.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/container_unix_mock.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/engine_mock.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/selinux_label_mock.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/isulad_config_mock.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/storage_mock.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/image_mock.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks/storage_mock.cc ++ verify_ut.cc) ++ ++target_include_directories(${EXE} PUBLIC ++ ${GTEST_INCLUDE_DIR} ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../include ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/modules/image/oci ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/modules/image ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/modules/image/external ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/common ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/cutils/map ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cmd/isulad ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/config ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/common ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/modules/api ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/modules/volume ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/modules/runtime ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/modules/container ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/modules/container/restart_manager ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/modules/container/health_check ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/modules/image/oci/storage ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/services ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/services/execution ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/modules/spec/ ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/services/execution/manager ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/modules/events ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/services/execution/execute ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/tar ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/plugin ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/http ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/modules/runtime/engines ++ ${ENGINES_INCS} ++ ${RUNTIME_INCS} ++ ${IMAGE_INCS} ++ ${CMAKE_BINARY_DIR}/conf ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/sha256 ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/config ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/cmd ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/daemon/services/graphdriver ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../src/utils/console ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/image/oci ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../test/mocks ++ ) ++ ++target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${ISULA_LIBUTILS_LIBRARY} -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) ++add_test(NAME ${EXE} COMMAND ${EXE} --gtest_output=xml:${EXE}-Results.xml) ++set_tests_properties(${EXE} PROPERTIES TIMEOUT 120) +diff --git a/test/specs/verify/verify_ut.cc b/test/specs/verify/verify_ut.cc +new file mode 100644 +index 00000000..e764e476 +--- /dev/null ++++ b/test/specs/verify/verify_ut.cc +@@ -0,0 +1,173 @@ ++/* ++ * 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. ++ * Description: specs verify ut ++ * Author: xuxuepeng ++ * Create: 2023-11-16 ++ */ ++ ++#include ++#include ++#include ++#include "mock.h" ++#include ++#include ++#include "sysinfo.h" ++#include "utils.h" ++ ++using namespace std; ++ ++#define HOST_CONFIG_FILE "../../../../test/specs/verify/hostconfig.json" ++#define OCI_RUNTIME_SPEC_FILE "../../../../test/specs/verify/oci_runtime_spec.json" ++ ++extern "C" { ++ int verify_resources_cpuset(const sysinfo_t *sysinfo, const char *cpus, const char *mems); ++} ++ ++/* get sys info */ ++sysinfo_t *create_sys_info_for_cpuset_test(const char *cpus, const char *mems, int ncpus_conf, int ncpus) ++{ ++ sysinfo_t *sysinfo = NULL; ++ ++ sysinfo = (sysinfo_t *)util_common_calloc_s(sizeof(sysinfo_t)); ++ if (sysinfo == NULL) { ++ ERROR("Out of memory"); ++ return NULL; ++ } ++ ++ sysinfo->ncpus = ncpus; ++ sysinfo->ncpus_conf = ncpus_conf; ++ ++ sysinfo->cpusetinfo.cpuset = true; ++ sysinfo->cpusetinfo.cpus = util_strdup_s(cpus); ++ sysinfo->cpusetinfo.mems = util_strdup_s(mems); ++ ++ return sysinfo; ++} ++ ++void test_different_provided_cpus_mems(sysinfo_t *sysinfo, const char *provided_cpus, const char *provided_mems, ++ int expected) ++{ ++ int ret = 0; ++ ret = verify_resources_cpuset(sysinfo, provided_cpus, provided_mems); ++ ASSERT_EQ(ret, expected); ++} ++ ++// Test the case when provided is null, and available is 0-7 ++TEST(test_verify_resources_cpuset, test_0_7) ++{ ++ sysinfo_t *sysinfo = create_sys_info_for_cpuset_test("0-7", "0-7", 8, 8); ++ test_different_provided_cpus_mems(sysinfo, nullptr, nullptr, 0); ++ ++ test_different_provided_cpus_mems(sysinfo, "0", "0", 0); ++ test_different_provided_cpus_mems(sysinfo, "2", "2", 0); ++ test_different_provided_cpus_mems(sysinfo, "7", "7", 0); ++ test_different_provided_cpus_mems(sysinfo, "8", "8", -1); ++ ++ test_different_provided_cpus_mems(sysinfo, "1,2", "1,2", 0); ++ test_different_provided_cpus_mems(sysinfo, "1,3,5", "1,3,5", 0); ++ ++ test_different_provided_cpus_mems(sysinfo, "0-7", "0-7", 0); ++ test_different_provided_cpus_mems(sysinfo, "0-8", "0-8", -1); ++ test_different_provided_cpus_mems(sysinfo, "0-1,3-7", "0-1,3-7", 0); ++ test_different_provided_cpus_mems(sysinfo, "0-1,3,5-7", "0-1,3,5-7", 0); ++ ++ free_sysinfo(sysinfo); ++} ++ ++// Test the case when provided is null, and available is 0-1,3-7 ++TEST(test_verify_resources_cpuset, test_0_1_3_7) ++{ ++ sysinfo_t *sysinfo = create_sys_info_for_cpuset_test("0-1,3-7", "0-1,3-7", 8, 7); ++ test_different_provided_cpus_mems(sysinfo, nullptr, nullptr, 0); ++ ++ test_different_provided_cpus_mems(sysinfo, "0", "0", 0); ++ test_different_provided_cpus_mems(sysinfo, "2", "2", -1); ++ test_different_provided_cpus_mems(sysinfo, "7", "7", 0); ++ test_different_provided_cpus_mems(sysinfo, "8", "8", -1); ++ ++ test_different_provided_cpus_mems(sysinfo, "1,2", "1,2", -1); ++ test_different_provided_cpus_mems(sysinfo, "1,3,5", "1,3,5", 0); ++ ++ test_different_provided_cpus_mems(sysinfo, "0-7", "0-7", -1); ++ test_different_provided_cpus_mems(sysinfo, "0-8", "0-8", -1); ++ test_different_provided_cpus_mems(sysinfo, "0-1,3-7", "0-1,3-7", 0); ++ test_different_provided_cpus_mems(sysinfo, "0-1,3,5-7", "0-1,3,5-7", 0); ++ ++ free_sysinfo(sysinfo); ++} ++ ++// Test the case when provided is null, and available is 0-6 ++TEST(test_verify_resources_cpuset, test_0_6) ++{ ++ sysinfo_t *sysinfo = create_sys_info_for_cpuset_test("0-6", "0-6", 8, 7); ++ ++ test_different_provided_cpus_mems(sysinfo, nullptr, nullptr, 0); ++ ++ test_different_provided_cpus_mems(sysinfo, "0", "0", 0); ++ test_different_provided_cpus_mems(sysinfo, "2", "2", 0); ++ test_different_provided_cpus_mems(sysinfo, "7", "7", -1); ++ test_different_provided_cpus_mems(sysinfo, "8", "8", -1); ++ ++ test_different_provided_cpus_mems(sysinfo, "1,2", "1,2", 0); ++ test_different_provided_cpus_mems(sysinfo, "1,3,5", "1,3,5", 0); ++ ++ test_different_provided_cpus_mems(sysinfo, "0-7", "0-7", -1); ++ test_different_provided_cpus_mems(sysinfo, "0-8", "0-8", -1); ++ test_different_provided_cpus_mems(sysinfo, "0-1,3-7", "0-1,3-7", -1); ++ test_different_provided_cpus_mems(sysinfo, "0-1,3,5-7", "0-1,3,5-7", -1); ++ ++ free_sysinfo(sysinfo); ++} ++ ++// Test the case when provided is null, and available is 1-7 ++TEST(test_verify_resources_cpuset, test_1_7) ++{ ++ sysinfo_t *sysinfo = create_sys_info_for_cpuset_test("1-7", "1-7", 8, 7); ++ ++ test_different_provided_cpus_mems(sysinfo, nullptr, nullptr, 0); ++ ++ test_different_provided_cpus_mems(sysinfo, "0", "0", -1); ++ test_different_provided_cpus_mems(sysinfo, "2", "2", 0); ++ test_different_provided_cpus_mems(sysinfo, "7", "7", 0); ++ test_different_provided_cpus_mems(sysinfo, "8", "8", -1); ++ ++ test_different_provided_cpus_mems(sysinfo, "1,2", "1,2", 0); ++ test_different_provided_cpus_mems(sysinfo, "1,3,5", "1,3,5", 0); ++ ++ test_different_provided_cpus_mems(sysinfo, "0-7", "0-7", -1); ++ test_different_provided_cpus_mems(sysinfo, "0-8", "0-8", -1); ++ test_different_provided_cpus_mems(sysinfo, "0-1,3-7", "0-1,3-7", -1); ++ test_different_provided_cpus_mems(sysinfo, "0-1,3,5-7", "0-1,3,5-7", -1); ++ ++ free_sysinfo(sysinfo); ++} ++ ++// Test the case when provided is null, and available is 0,3 ++TEST(test_verify_resources_cpuset, test_null_03) ++{ ++ sysinfo_t *sysinfo = create_sys_info_for_cpuset_test("0,3", "0,3", 8, 2); ++ test_different_provided_cpus_mems(sysinfo, nullptr, nullptr, 0); ++ ++ test_different_provided_cpus_mems(sysinfo, "0", "0", 0); ++ test_different_provided_cpus_mems(sysinfo, "2", "2", -1); ++ test_different_provided_cpus_mems(sysinfo, "7", "7", -1); ++ test_different_provided_cpus_mems(sysinfo, "8", "8", -1); ++ ++ test_different_provided_cpus_mems(sysinfo, "1,2", "1,2", -1); ++ test_different_provided_cpus_mems(sysinfo, "1,3,5", "1,3,5", -1); ++ ++ test_different_provided_cpus_mems(sysinfo, "0-7", "0-7", -1); ++ test_different_provided_cpus_mems(sysinfo, "0-8", "0-8", -1); ++ test_different_provided_cpus_mems(sysinfo, "0-1,3-7", "0-1,3-7", -1); ++ test_different_provided_cpus_mems(sysinfo, "0-1,3,5-7", "0-1,3,5-7", -1); ++ ++ free_sysinfo(sysinfo); ++} +-- +2.42.0 + diff --git a/0030-modify-daemon-json-default-runtime-to-runc.patch b/0030-modify-daemon-json-default-runtime-to-runc.patch new file mode 100644 index 0000000..dd09a65 --- /dev/null +++ b/0030-modify-daemon-json-default-runtime-to-runc.patch @@ -0,0 +1,52 @@ +From b94f36b3d06abd711449b2e91303dfdd33f9c979 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Tue, 21 Nov 2023 21:31:48 +0800 +Subject: [PATCH 30/64] modify daemon json default runtime to runc + +Signed-off-by: zhongtao +--- + src/cmd/isula/base/create.h | 2 +- + src/cmd/isula/extend/stats.c | 1 - + src/contrib/config/daemon.json | 2 +- + 3 files changed, 2 insertions(+), 3 deletions(-) + +diff --git a/src/cmd/isula/base/create.h b/src/cmd/isula/base/create.h +index 986be41f..9eb471b4 100644 +--- a/src/cmd/isula/base/create.h ++++ b/src/cmd/isula/base/create.h +@@ -332,7 +332,7 @@ extern "C" { + "runtime", \ + 'R', \ + &(cmdargs).runtime, \ +- "Runtime to use for containers(default: lcr)", \ ++ "Runtime to use for containers", \ + NULL }, \ + { CMD_OPT_TYPE_STRING_DUP, \ + false, \ +diff --git a/src/cmd/isula/extend/stats.c b/src/cmd/isula/extend/stats.c +index c11fe218..04485608 100644 +--- a/src/cmd/isula/extend/stats.c ++++ b/src/cmd/isula/extend/stats.c +@@ -41,7 +41,6 @@ struct client_arguments g_cmd_stats_args = { + .showall = false, + .nostream = false, + .original = false, +- .runtime = "lcr", + }; + + static struct isula_stats_response *g_oldstats = NULL; +diff --git a/src/contrib/config/daemon.json b/src/contrib/config/daemon.json +index 4faf4057..966e016a 100644 +--- a/src/contrib/config/daemon.json ++++ b/src/contrib/config/daemon.json +@@ -1,6 +1,6 @@ + { + "group": "isula", +- "default-runtime": "lcr", ++ "default-runtime": "runc", + "graph": "/var/lib/isulad", + "state": "/var/run/isulad", + "log-level": "ERROR", +-- +2.42.0 + diff --git a/0031-modify-CI-for-default-runtime-to-runc.patch b/0031-modify-CI-for-default-runtime-to-runc.patch new file mode 100644 index 0000000..9b8f8d8 --- /dev/null +++ b/0031-modify-CI-for-default-runtime-to-runc.patch @@ -0,0 +1,815 @@ +From c0d86490ba53bf9a33f7569dc31c4ec1ba54f073 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Tue, 21 Nov 2023 21:32:08 +0800 +Subject: [PATCH 31/64] modify CI for default runtime to runc + +Signed-off-by: zhongtao +--- + CI/test_cases/container_cases/cni_test.sh | 103 ++++++++++-------- + .../container_cases/exec_additional_gids.sh | 26 +++-- + CI/test_cases/container_cases/export.sh | 10 +- + .../hook_ignore_poststart_error.sh | 10 +- + .../container_cases/hook_spec_test.sh | 12 +- + ...igdata_stream.sh => lcr_bigdata_stream.sh} | 32 +----- + .../container_cases/{exec.sh => lcr_exec.sh} | 2 +- + CI/test_cases/container_cases/nano_cpus.sh | 8 +- + CI/test_cases/container_cases/restart.sh | 14 ++- + CI/test_cases/container_cases/run.sh | 49 +++++---- + ..._stream_runc.sh => runc_bigdata_stream.sh} | 0 + .../{exec_runc.sh => runc_exec.sh} | 0 + CI/test_cases/container_cases/seccomp.sh | 12 +- + CI/test_cases/container_cases/stop.sh | 19 +++- + CI/test_cases/critest.sh | 6 +- + 15 files changed, 166 insertions(+), 137 deletions(-) + rename CI/test_cases/container_cases/{bigdata_stream.sh => lcr_bigdata_stream.sh} (93%) + rename CI/test_cases/container_cases/{exec.sh => lcr_exec.sh} (97%) + rename CI/test_cases/container_cases/{bigdata_stream_runc.sh => runc_bigdata_stream.sh} (100%) + rename CI/test_cases/container_cases/{exec_runc.sh => runc_exec.sh} (100%) + +diff --git a/CI/test_cases/container_cases/cni_test.sh b/CI/test_cases/container_cases/cni_test.sh +index bbc381dd..114cf2a3 100755 +--- a/CI/test_cases/container_cases/cni_test.sh ++++ b/CI/test_cases/container_cases/cni_test.sh +@@ -37,6 +37,10 @@ function do_post() + start_isulad_with_valgrind + } + ++# $1: pod runtime; ++# $2: pod config; ++# $3: eth0 ip; ++# $4: eth1 ip; + function do_test_help() + { + msg_info "this is $0 do_test" +@@ -53,7 +57,7 @@ function do_test_help() + TC_RET_T=$(($TC_RET_T+1)) + fi + +- sid=`crictl runp ${data_path}/$1` ++ sid=`crictl runp --runtime $1 ${data_path}/$2` + if [ $? -ne 0 ]; then + msg_err "Failed to run sandbox" + TC_RET_T=$(($TC_RET_T+1)) +@@ -61,7 +65,7 @@ function do_test_help() + + cnt=`ls /var/lib/cni/results/* | wc -l` + target_cnt=1 +- if [ "x$3" != "x" ];then ++ if [ "x$4" != "x" ];then + target_cnt=2 + fi + +@@ -77,7 +81,7 @@ function do_test_help() + TC_RET_T=$(($TC_RET_T+1)) + fi + +- cid=`crictl create $sid ${data_path}/container-config.json ${data_path}/$1` ++ cid=`crictl create $sid ${data_path}/container-config.json ${data_path}/$2` + if [ $? -ne 0 ];then + msg_err "create container failed" + TC_RET_T=$(($TC_RET_T+1)) +@@ -107,29 +111,29 @@ function do_test_help() + nsenter -t $con_pid -n ifconfig eth0 + TC_RET_T=$(($TC_RET_T+1)) + fi +- nsenter -t $pod_pid -n ifconfig eth0 | grep "$2" ++ nsenter -t $pod_pid -n ifconfig eth0 | grep "$3" + if [ $? -ne 0 ];then +- msg_err "expect ip: $1, get: " ++ msg_err "expect ip: $3, get: " + nsenter -t $pod_pid -n ifconfig eth0 + TC_RET_T=$(($TC_RET_T+1)) + fi +- crictl inspectp $sid | grep "$2" ++ crictl inspectp $sid | grep "$3" + if [ $? -ne 0 ];then +- msg_err "inspectp: expect ip: $1, get: " ++ msg_err "inspectp: expect ip: $3, get: " + crictl inspectp $sid + TC_RET_T=$(($TC_RET_T+1)) + fi + +- if [ "x$3" != "x" ];then +- nsenter -t $pod_pid -n ifconfig eth1 | grep "$3" ++ if [ "x$4" != "x" ];then ++ nsenter -t $pod_pid -n ifconfig eth1 | grep "$4" + if [ $? -ne 0 ];then +- msg_err "expect ip: $2, get: " ++ msg_err "expect ip: $4, get: " + nsenter -t $pod_pid -n ifconfig eth1 + TC_RET_T=$(($TC_RET_T+1)) + fi +- crictl inspectp $sid | grep "$3" ++ crictl inspectp $sid | grep "$4" + if [ $? -ne 0 ];then +- msg_err "inspectp expect ip: $2, get: " ++ msg_err "inspectp expect ip: $4, get: " + crictl inspectp $sid + TC_RET_T=$(($TC_RET_T+1)) + fi +@@ -170,7 +174,7 @@ function do_test_help() + + function default_cni_config() + { +- do_test_help "sandbox-config.json" "10\.1\." ++ do_test_help $1 "sandbox-config.json" "10\.1\." + } + + function new_cni_config() +@@ -189,12 +193,12 @@ function new_cni_config() + fi + done + tail $ISUALD_LOG +- do_test_help "mutlnet_pod.json" "10\.2\." "10\.1\." ++ do_test_help $1 "mutlnet_pod.json" "10\.2\." "10\.1\." + } + + function check_annotation_extension() + { +- sid=`crictl runp ${data_path}/sandbox-config.json` ++ sid=`crictl runp --runtime $1 ${data_path}/sandbox-config.json` + if [ $? -ne 0 ]; then + msg_err "Failed to run sandbox" + TC_RET_T=$(($TC_RET_T+1)) +@@ -253,7 +257,7 @@ function check_rollback() + done + tail $ISUALD_LOG + +- crictl runp ${data_path}/mutl_wrong_net_pod.json ++ crictl runp --runtime $1 ${data_path}/mutl_wrong_net_pod.json + if [ $? -eq 0 ]; then + msg_err "Run sandbox success with invalid cni configs" + TC_RET_T=$(($TC_RET_T+1)) +@@ -302,13 +306,14 @@ function check_rollback() + # $2: expect ingress rate; + # $3: input egress rate; + # $4: expect egress rate; ++# $5: pod runtime; + function check_annotation_valid_bandwidth() + { + rm bandwidth.json + cp ${data_path}/mock_sandbox.json bandwidth.json + sed -i "s#ingressholder#$1#g" bandwidth.json + sed -i "s#engressholder#$3#g" bandwidth.json +- sid=`crictl runp bandwidth.json` ++ sid=`crictl runp --runtime $5 bandwidth.json` + if [ $? -ne 0 ]; then + msg_err "Failed to run sandbox" + TC_RET_T=$(($TC_RET_T+1)) +@@ -345,6 +350,7 @@ function check_annotation_valid_bandwidth() + return $TC_RET_T + } + ++# function not called + function check_annotation_invalid_bandwidth() + { + rm bandwidth.json +@@ -386,44 +392,51 @@ function check_annotation() + done + tail $ISUALD_LOG + +- check_annotation_extension ++ check_annotation_extension $1 + +- check_annotation_valid_bandwidth "10.24k" "10240" "-1.024k" "-1024" +- check_annotation_valid_bandwidth "1024m" "2" "-1024m" "-1" +- check_annotation_valid_bandwidth "1.000001Ki" "1025" "-1.00001Ki" "-1024" +- check_annotation_valid_bandwidth "0.1Mi" "104858" "-0.01Mi" "-10485" +- check_annotation_valid_bandwidth "1.00001e2" "101" "-1.0001e2" "-100" ++ check_annotation_valid_bandwidth "10.24k" "10240" "-1.024k" "-1024" $1 ++ check_annotation_valid_bandwidth "1024m" "2" "-1024m" "-1" $1 ++ check_annotation_valid_bandwidth "1.000001Ki" "1025" "-1.00001Ki" "-1024" $1 ++ check_annotation_valid_bandwidth "0.1Mi" "104858" "-0.01Mi" "-10485" $1 ++ check_annotation_valid_bandwidth "1.00001e2" "101" "-1.0001e2" "-100" $1 + + return $TC_RET_T + } + +-ret=0 ++function do_test_t() ++{ ++ local ret=0 ++ local runtime=$1 ++ local test="cni_test => (${runtime})" ++ msg_info "${test} starting..." ++ ++ default_cni_config $runtime || ((ret++)) ++ ++ new_cni_config $runtime || ((ret++)) ++ ++ check_annotation $runtime || ((ret++)) + +-do_pre +-if [ $? -ne 0 ];then +- let "ret=$ret + 1" +-fi ++ check_rollback $runtime || ((ret++)) + +-default_cni_config +-if [ $? -ne 0 ];then +- let "ret=$ret + 1" +-fi ++ msg_info "${test} finished with return ${ret}..." + +-new_cni_config +-if [ $? -ne 0 ];then +- let "ret=$ret + 1" +-fi ++ return $ret ++} + +-check_annotation +-if [ $? -ne 0 ];then +- let "ret=$ret + 1" +-fi ++ret=0 + +-check_rollback +-if [ $? -ne 0 ];then +- let "ret=$ret + 1" +-fi ++for element in ${RUNTIME_LIST[@]}; ++do ++ do_pre ++ if [ $? -ne 0 ];then ++ let "ret=$ret + 1" ++ fi + +-do_post ++ do_test_t $element ++ if [ $? -ne 0 ];then ++ let "ret=$ret + 1" ++ fi ++ do_post ++done + + show_result $ret "cni base test" +diff --git a/CI/test_cases/container_cases/exec_additional_gids.sh b/CI/test_cases/container_cases/exec_additional_gids.sh +index f24678d3..2edfd750 100755 +--- a/CI/test_cases/container_cases/exec_additional_gids.sh ++++ b/CI/test_cases/container_cases/exec_additional_gids.sh +@@ -22,7 +22,6 @@ + curr_path=$(dirname $(readlink -f "$0")) + data_path=$(realpath $curr_path/../data) + source ../helpers.sh +-test="exec additional gids test => test_exec_additional_gids" + test_log=$(mktemp /tmp/additional_gids_test_XXX) + + USERNAME="user" +@@ -37,10 +36,14 @@ file_info="Keep it secret, keep it safe" + function additional_gids_test() + { + local ret=0 ++ local runtime=$1 ++ test="exec additional gids test => test_exec_additional_gids => $runtime" ++ ++ msg_info "${test} starting..." + + isula rm -f `isula ps -a -q` + +- isula run -tid -n $cont_name ubuntu bash ++ isula run -tid --runtime $runtime -n $cont_name ubuntu bash + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to run container" && ((ret++)) + + isula exec $cont_name bash -c "groupadd --gid $USER_GID $USERNAME \ +@@ -52,10 +55,13 @@ function additional_gids_test() + && chmod 606 /app/sekrit.txt" + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - create user and group failed" && ((ret++)) + ++ # runc is not support exec --workdir + /usr/bin/expect <<- EOF > ${test_log} 2>&1 + set timeout 10 +-spawn isula exec -it --workdir /app -u $USERNAME $cont_name bash ++spawn isula exec -it -u $USERNAME $cont_name bash + expect "${USERNAME}*" ++send "cd /app\n" ++expect "*" + send "newgrp ${ADDITIONAL_GROUP}\n" + expect "*" + send "groups\n" +@@ -75,18 +81,18 @@ EOF + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - read error message failed" && ((ret++)) + + isula rm -f `isula ps -a -q` ++ rm -rf ${test_log} ++ ++ msg_info "${test} finished with return ${ret}..." + + return ${ret} + } + + declare -i ans=0 + +-msg_info "${test} starting..." +- +-additional_gids_test || ((ans++)) +- +-rm -rf ${test_log} +- +-msg_info "${test} finished with return ${ret}..." ++for element in ${RUNTIME_LIST[@]}; ++do ++ additional_gids_test $element || ((ans++)) ++done + + show_result ${ans} "${curr_path}/${0}" +diff --git a/CI/test_cases/container_cases/export.sh b/CI/test_cases/container_cases/export.sh +index eeef2809..1cff873d 100755 +--- a/CI/test_cases/container_cases/export.sh ++++ b/CI/test_cases/container_cases/export.sh +@@ -26,7 +26,8 @@ function test_image_export() + { + local ret=0 + local image="busybox" +- local test="export container test => (${FUNCNAME[@]})" ++ local runtime=$1 ++ local test="export container test => (${FUNCNAME[@]}) => $runtime" + + msg_info "${test} starting..." + +@@ -36,7 +37,7 @@ function test_image_export() + isula images | grep busybox + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - missing list image: ${image}" && ((ret++)) + +- CONT=`isula run -itd busybox` ++ CONT=`isula run --runtime $runtime -itd busybox` + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to run container with image: ${image}" && ((ret++)) + + isula export -o export.tar ${CONT} +@@ -55,6 +56,9 @@ function test_image_export() + + declare -i ans=0 + +-test_image_export || ((ans++)) ++for element in ${RUNTIME_LIST[@]}; ++do ++ test_image_export $element || ((ans++)) ++done + + show_result ${ans} "${curr_path}/${0}" +diff --git a/CI/test_cases/container_cases/hook_ignore_poststart_error.sh b/CI/test_cases/container_cases/hook_ignore_poststart_error.sh +index 5c86a4c1..8c636f7e 100755 +--- a/CI/test_cases/container_cases/hook_ignore_poststart_error.sh ++++ b/CI/test_cases/container_cases/hook_ignore_poststart_error.sh +@@ -28,7 +28,8 @@ function test_hook_ignore_poststart_error_spec() + { + local ret=0 + local image="busybox" +- local test="container hook test => (${FUNCNAME[@]})" ++ local runtime=$1 ++ local test="container hook test => (${FUNCNAME[@]}) => $runtime" + CONT=test_hook_spec + cp ${test_data_path}/poststart.sh /tmp/ + +@@ -40,7 +41,7 @@ function test_hook_ignore_poststart_error_spec() + isula images | grep busybox + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - missing list image: ${image}" && ((ret++)) + +- isula run -n $CONT -itd --hook-spec ${test_data_path}/oci_hook_poststart_check.json ${image} & ++ isula run -n $CONT -itd --runtime $runtime --hook-spec ${test_data_path}/oci_hook_poststart_check.json ${image} & + + for a in `seq 20` + do +@@ -74,6 +75,9 @@ function test_hook_ignore_poststart_error_spec() + + declare -i ans=0 + +-test_hook_ignore_poststart_error_spec || ((ans++)) ++for element in ${RUNTIME_LIST[@]}; ++do ++ test_hook_ignore_poststart_error_spec $1 || ((ans++)) ++done + + show_result ${ans} "${curr_path}/${0}" +diff --git a/CI/test_cases/container_cases/hook_spec_test.sh b/CI/test_cases/container_cases/hook_spec_test.sh +index c88ed340..33b7c2e5 100755 +--- a/CI/test_cases/container_cases/hook_spec_test.sh ++++ b/CI/test_cases/container_cases/hook_spec_test.sh +@@ -28,7 +28,8 @@ function test_hook_spec() + { + local ret=0 + local image="busybox" +- local test="container hook test => (${FUNCNAME[@]})" ++ local runtime=$1 ++ local test="container hook test => (${FUNCNAME[@]}) => $runtime" + msg_info "${test} starting..." + + isula pull ${image} +@@ -37,7 +38,7 @@ function test_hook_spec() + isula images | grep busybox + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - missing list image: ${image}" && ((ret++)) + +- CONT=`isula run -itd --hook-spec ${test_data_path}/test-hookspec.json ${image}` ++ CONT=`isula run -itd --runtime $runtime --hook-spec ${test_data_path}/test-hookspec.json ${image}` + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to run container with image: ${image}" && ((ret++)) + + isula stop -t 0 ${CONT} +@@ -51,7 +52,7 @@ function test_hook_spec() + isula run -n $no_permission_container -itd --hook-spec ${test_data_path}/no_permission.json ${image} > $runlog 2>&1 + [[ $? -ne 126 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to check exit code container with image: ${image}" && ((ret++)) + +- cat $runlog | grep "Permission denied" ++ cat $runlog | grep -i "Permission denied" + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to get no_permission output: ${image}" && ((ret++)) + + isula rm -f $no_permission_container +@@ -95,6 +96,9 @@ EOF + + declare -i ans=0 + +-test_hook_spec || ((ans++)) ++for element in ${RUNTIME_LIST[@]}; ++do ++ test_hook_spec $element || ((ans++)) ++done + + show_result ${ans} "${curr_path}/${0}" +diff --git a/CI/test_cases/container_cases/bigdata_stream.sh b/CI/test_cases/container_cases/lcr_bigdata_stream.sh +similarity index 93% +rename from CI/test_cases/container_cases/bigdata_stream.sh +rename to CI/test_cases/container_cases/lcr_bigdata_stream.sh +index 3bfc2d50..c8ecc48a 100755 +--- a/CI/test_cases/container_cases/bigdata_stream.sh ++++ b/CI/test_cases/container_cases/lcr_bigdata_stream.sh +@@ -40,7 +40,7 @@ function set_up() + isula images | grep busybox + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - missing list image: ${image}" && ((ret++)) + +- CID=$(isula run -itd ${image} sh) ++ CID=$(isula run --runtime lcr -itd ${image} sh) + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to run container with image: ${image}" && ((ret++)) + + isula exec -it $CID dd if=/dev/zero of=test_500M bs=1M count=500 +@@ -389,33 +389,6 @@ function test_stream_with_kill_isulad() + return ${ret} + } + +-function test_stream_with_runc() +-{ +- local ret=0 +- local image="busybox" +- local test="test_stream_with_runc => (${FUNCNAME[@]})" +- msg_info "${test} starting..." +- +- RUNCID=$(isula run -itd --runtime runc ${image} sh) +- isula exec -it $RUNCID dd if=/dev/zero of=test_500M bs=1M count=500 +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to create bigdata" && ((ret++)) +- +- isula exec -it $RUNCID cat test_500M > /home/iocopy_stream_data_500M +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to cat bigdata" && ((ret++)) +- +- sync && sync +- total_size=$(stat -c"%s" /home/iocopy_stream_data_500M) +- [[ $total_size -ne 524288000 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - stream iocopy loss data" && ((ret++)) +- +- isula rm -f $RUNCID +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to rm container" && ((ret++)) +- +- rm -rf /home/iocopy_stream_data_500M +- +- msg_info "${test} finished with return ${ret}..." +- return ${ret} +-} +- + function tear_down() + { + local ret=0 +@@ -438,7 +411,7 @@ function test_memory_leak_with_bigdata_stream() + + start_isulad_with_valgrind + +- CID=$(isula run -itd ${image} sh) ++ CID=$(isula run --runtime lcr -itd ${image} sh) + + isula exec -it $CID dd if=/dev/zero of=test_100M bs=1M count=100 + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to create bigdata" && ((ret++)) +@@ -477,7 +450,6 @@ test_stream_with_stop_lxc_monitor || ((ans++)) + test_stream_with_kill_lxc_monitor || ((ans++)) + test_stream_with_stop_isulad || ((ans++)) + test_stream_with_kill_isulad || ((ans++)) +-test_stream_with_runc || ((ans++)) + tear_down || ((ans++)) + + test_memory_leak_with_bigdata_stream || ((ans++)) +diff --git a/CI/test_cases/container_cases/exec.sh b/CI/test_cases/container_cases/lcr_exec.sh +similarity index 97% +rename from CI/test_cases/container_cases/exec.sh +rename to CI/test_cases/container_cases/lcr_exec.sh +index 96ceb884..4f51773d 100755 +--- a/CI/test_cases/container_cases/exec.sh ++++ b/CI/test_cases/container_cases/lcr_exec.sh +@@ -30,7 +30,7 @@ function exec_workdir() + + isula rm -f `isula ps -a -q` + +- isula run -tid -n cont_workdir busybox sh ++ isula run -tid --runtime lcr -n cont_workdir busybox sh + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to run container with --workdir" && ((ret++)) + + isula exec -ti --workdir /workdir cont_workdir pwd | grep "/workdir" +diff --git a/CI/test_cases/container_cases/nano_cpus.sh b/CI/test_cases/container_cases/nano_cpus.sh +index c679958d..85223038 100755 +--- a/CI/test_cases/container_cases/nano_cpus.sh ++++ b/CI/test_cases/container_cases/nano_cpus.sh +@@ -26,7 +26,8 @@ function test_cpu_nano_spec() + { + local ret=0 + local image="busybox" +- local test="container blkio nano test => (${FUNCNAME[@]})" ++ local runtime=$1 ++ local test="container blkio nano test => (${FUNCNAME[@]}) => $runtime" + + msg_info "${test} starting..." + +@@ -108,6 +109,9 @@ function test_cpu_nano_spec() + + declare -i ans=0 + +-test_cpu_nano_spec || ((ans++)) ++for element in ${RUNTIME_LIST[@]}; ++do ++ test_cpu_nano_spec $element || ((ans++)) ++done + + show_result ${ans} "${curr_path}/${0}" +diff --git a/CI/test_cases/container_cases/restart.sh b/CI/test_cases/container_cases/restart.sh +index 5902af06..fddee1f7 100755 +--- a/CI/test_cases/container_cases/restart.sh ++++ b/CI/test_cases/container_cases/restart.sh +@@ -26,7 +26,8 @@ source ../helpers.sh + function do_test_t() + { + containername=test_restart +- isula run --name $containername -td busybox ++ ++ isula run --runtime $1 --name $containername -td busybox + fn_check_eq "$?" "0" "run failed" + testcontainer $containername running + +@@ -46,9 +47,12 @@ function do_test_t() + + ret=0 + +-do_test_t +-if [ $? -ne 0 ];then +- let "ret=$ret + 1" +-fi ++for element in ${RUNTIME_LIST[@]}; ++do ++ do_test_t $element ++ if [ $? -ne 0 ];then ++ let "ret=$ret + 1" ++ fi ++done + + show_result $ret "basic restart" +diff --git a/CI/test_cases/container_cases/run.sh b/CI/test_cases/container_cases/run.sh +index ad449402..8ea3e514 100755 +--- a/CI/test_cases/container_cases/run.sh ++++ b/CI/test_cases/container_cases/run.sh +@@ -25,7 +25,7 @@ source ../helpers.sh + + function do_test_t() + { +- tid=`isula run -tid --name hostname busybox` ++ tid=`isula run --runtime $1 -tid --name hostname busybox` + chostname=`isula exec -it $tid hostname` + fn_check_eq "$chostname" "${tid:0:12}" "default hostname is id of container" + isula exec -it hostname env | grep HOSTNAME +@@ -37,7 +37,7 @@ function do_test_t() + containername=test_basic_run + containername2=container_to_join + +- isula run --name $containername -td busybox ++ isula run --runtime $1 --name $containername -td busybox + fn_check_eq "$?" "0" "run failed" + testcontainer $containername running + +@@ -48,7 +48,7 @@ function do_test_t() + isula rm $containername + fn_check_eq "$?" "0" "rm failed" + +- isula run --name $containername -td -v /dev/shm:/dev/shm busybox ++ isula run --runtime $1 --name $containername -td -v /dev/shm:/dev/shm busybox + fn_check_eq "$?" "0" "run failed" + testcontainer $containername running + +@@ -61,7 +61,7 @@ function do_test_t() + + echo AA > /tmp/test_run_env + +- isula run --name $containername -itd --user 100:100 -e AAA=BB -e BAA --env-file /tmp/test_run_env busybox ++ isula run --runtime $1 --name $containername -itd --user 100:100 -e AAA=BB -e BAA --env-file /tmp/test_run_env busybox + fn_check_eq "$?" "0" "run failed" + testcontainer $containername running + +@@ -72,18 +72,21 @@ function do_test_t() + isula rm $containername + fn_check_eq "$?" "0" "rm failed" + +- isula run --name $containername -itd --external-rootfs / --read-only none sh +- fn_check_eq "$?" "0" "run container with host rootfs failed" +- testcontainer $containername running ++ # runc directly uses the root directory as external rootfs and will report the error pivot_root .: device or resource busy ++ if [ $runtime == "lcr" ]; then ++ isula run --runtime $1 --name $containername -itd --external-rootfs / --read-only none sh ++ fn_check_eq "$?" "0" "run container with host rootfs failed" ++ testcontainer $containername running + +- isula stop -t 0 $containername +- fn_check_eq "$?" "0" "stop failed" +- testcontainer $containername exited ++ isula stop -t 0 $containername ++ fn_check_eq "$?" "0" "stop failed" ++ testcontainer $containername exited + +- isula rm $containername +- fn_check_eq "$?" "0" "rm failed" ++ isula rm $containername ++ fn_check_eq "$?" "0" "rm failed" ++ fi + +- isula run --name $containername -itd --net=host --pid=host --ipc=host --uts=host busybox ++ isula run --runtime $1 --name $containername -itd --net=host --pid=host --ipc=host --uts=host busybox + fn_check_eq "$?" "0" "run failed" + testcontainer $containername running + +@@ -94,7 +97,7 @@ function do_test_t() + isula rm $containername + fn_check_eq "$?" "0" "rm failed" + +- isula run --name $containername -itd --net=none --pid=none --ipc=none --uts=none busybox ++ isula run --runtime $1 --name $containername -itd --net=none --pid=none --ipc=none --uts=none busybox + fn_check_eq "$?" "0" "run failed" + testcontainer $containername running + +@@ -105,11 +108,11 @@ function do_test_t() + isula rm $containername + fn_check_eq "$?" "0" "rm failed" + +- isula run --name $containername2 -itd busybox ++ isula run --runtime $1 --name $containername2 -itd busybox + fn_check_eq "$?" "0" "run failed" + testcontainer $containername2 running + +- isula run --name $containername -itd --net=container:$containername2 --pid=container:$containername2 --ipc=container:$containername2 --uts=container:$containername2 busybox ++ isula run --runtime $1 --name $containername -itd --net=container:$containername2 --pid=container:$containername2 --ipc=container:$containername2 --uts=container:$containername2 busybox + fn_check_eq "$?" "0" "run failed" + testcontainer $containername running + +@@ -135,7 +138,7 @@ function do_run_remote_test_t() + local ret=0 + local image="busybox" + local config='tcp://127.0.0.1:2890' +- local test="container start with --attach remote test => (${FUNCNAME[@]})" ++ local test="container start with --attach remote test => (${FUNCNAME[@]}) => $1" + + check_valgrind_log + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - stop isulad failed" && ((ret++)) +@@ -144,13 +147,13 @@ function do_run_remote_test_t() + + containername=run_remote + +- isula run -ti -H "$config" --name $containername busybox xxx ++ isula run --runtime $1 -ti -H "$config" --name $containername busybox xxx + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed check invalid run ${containername} remote" && ((ret++)) + testcontainer $containername exited + isula rm -f -H "$config" $containername + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to rm container remote" && ((ret++)) + +- isula run -ti -H "$config" --name $containername busybox /bin/sh -c 'echo "hello"' | grep hello ++ isula run --runtime $1 -ti -H "$config" --name $containername busybox /bin/sh -c 'echo "hello"' | grep hello + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to run ${containername} remote" && ((ret++)) + testcontainer $containername exited + +@@ -169,8 +172,10 @@ function do_run_remote_test_t() + + declare -i ans=0 + +-do_test_t || ((ans++)) +- +-do_run_remote_test_t || ((ans++)) ++for element in ${RUNTIME_LIST[@]}; ++do ++ do_test_t $element || ((ans++)) ++ do_run_remote_test_t $element || ((ans++)) ++done + + show_result ${ans} "${curr_path}/${0}" +diff --git a/CI/test_cases/container_cases/bigdata_stream_runc.sh b/CI/test_cases/container_cases/runc_bigdata_stream.sh +similarity index 100% +rename from CI/test_cases/container_cases/bigdata_stream_runc.sh +rename to CI/test_cases/container_cases/runc_bigdata_stream.sh +diff --git a/CI/test_cases/container_cases/exec_runc.sh b/CI/test_cases/container_cases/runc_exec.sh +similarity index 100% +rename from CI/test_cases/container_cases/exec_runc.sh +rename to CI/test_cases/container_cases/runc_exec.sh +diff --git a/CI/test_cases/container_cases/seccomp.sh b/CI/test_cases/container_cases/seccomp.sh +index 9e886d10..3cb08d84 100755 +--- a/CI/test_cases/container_cases/seccomp.sh ++++ b/CI/test_cases/container_cases/seccomp.sh +@@ -39,8 +39,9 @@ function do_pre() { + + function do_test() { + local ret=0 +- +- msg_info "this is $0 do_test" ++ local runtime=$1 ++ local test="seccomp test => (${runtime})" ++ msg_info "${test} starting..." + + cid1=$(isula run -tid --security-opt seccomp=/etc/isulad/seccomp_default.json busybox sh) + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - Failed to run container with the default seccomp profile" && ((ret++)) +@@ -52,7 +53,7 @@ function do_test() { + --security-opt seccomp=${test_data_path}/seccomp_profile_without_archmap.json busybox sh) + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - Failed to run container with multiple seccomp profiles" && ((ret++)) + +- isula stop "${cid1}" "${cid2}" "${cid3}" ++ isula stop -t 0 "${cid1}" "${cid2}" "${cid3}" + + isula rm -f $(isula ps -qa) + +@@ -69,7 +70,10 @@ declare -i ans=0 + + do_pre || ((ans++)) + +-do_test || ((ans++)) ++for element in ${RUNTIME_LIST[@]}; ++do ++ do_test $element || ((ans++)) ++done + + do_post + +diff --git a/CI/test_cases/container_cases/stop.sh b/CI/test_cases/container_cases/stop.sh +index 962e72f3..13292710 100755 +--- a/CI/test_cases/container_cases/stop.sh ++++ b/CI/test_cases/container_cases/stop.sh +@@ -25,8 +25,12 @@ source ../helpers.sh + + function do_test_t() + { ++ local runtime=$1 ++ local test="start_test => (${runtime})" ++ msg_info "${test} starting..." ++ + containername=test_stop +- isula run --name $containername -td busybox ++ isula run --runtime $runtime --name $containername -td busybox + fn_check_eq "$?" "0" "run failed" + testcontainer $containername running + +@@ -61,14 +65,19 @@ function do_test_t() + isula rm $containername + fn_check_eq "$?" "0" "rm failed" + ++ msg_info "${test} finished with return ${ret}..." ++ + return $TC_RET_T + } + + ret=0 + +-do_test_t +-if [ $? -ne 0 ];then +- let "ret=$ret + 1" +-fi ++for element in ${RUNTIME_LIST[@]}; ++do ++ do_test_t $element ++ if [ $? -ne 0 ];then ++ let "ret=$ret + 1" ++ fi ++done + + show_result $ret "basic stop" +diff --git a/CI/test_cases/critest.sh b/CI/test_cases/critest.sh +index 044ce2ed..f8d4975e 100755 +--- a/CI/test_cases/critest.sh ++++ b/CI/test_cases/critest.sh +@@ -130,7 +130,7 @@ function test_critest() { + function do_test_t() { + local ret=0 + +- local runtime="lcr" ++ local runtime="runc" + local test="critest => $runtime" + msg_info "${test} starting..." + echo "${test}" >> ${testcase_data}/critest.log +@@ -143,11 +143,11 @@ function do_test_t() { + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - stop isulad failed" && ((ret++)) + + # replace default runtime +- sed -i 's/"default-runtime": "lcr"/"default-runtime": "runc"/g' /etc/isulad/daemon.json ++ sed -i 's/"default-runtime": "runc"/"default-runtime": "lcr"/g' /etc/isulad/daemon.json + start_isulad_without_valgrind --selinux-enabled --network-plugin cni + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - start isulad with selinux and cni failed" && ((ret++)) + +- runtime=runc ++ runtime=lcr + test="critest => $runtime" + msg_info "${test} starting..." + echo "${test}" >> ${testcase_data}/critest.log +-- +2.42.0 + diff --git a/0032-add-ut-for-devicemapper.patch b/0032-add-ut-for-devicemapper.patch new file mode 100644 index 0000000..e28c5fa --- /dev/null +++ b/0032-add-ut-for-devicemapper.patch @@ -0,0 +1,737 @@ +From ca297d26dc1e7b47d6987c6bbbd92dd2e3d78670 Mon Sep 17 00:00:00 2001 +From: jikai +Date: Wed, 22 Nov 2023 22:05:04 +0800 +Subject: [PATCH 32/64] add ut for devicemapper + +Signed-off-by: jikai +--- + test/image/oci/storage/layers/CMakeLists.txt | 2 + + .../storage/layers/devmapper/CMakeLists.txt | 71 +++++ + ...9702e4bd316dd50ae85467b0378a419b23b60ba73d | 6 + + ...a9fb83febf6dc0b1548dfe896161533668281c9f4f | 6 + + ...0a625721fdbea5c94ca6da897acdd814d710149770 | 6 + + .../devmapper/data/devicemapper/metadata/base | 7 + + .../devicemapper/metadata/deviceset-metadata | 5 + + .../metadata/transaction-metadata | 5 + + .../layers/devmapper/driver_devmapper_ut.cc | 283 ++++++++++++++++++ + test/mocks/libdevmapper_mock.cc | 191 ++++++++++++ + test/mocks/libdevmapper_mock.h | 52 ++++ + 11 files changed, 634 insertions(+) + create mode 100644 test/image/oci/storage/layers/devmapper/CMakeLists.txt + create mode 100644 test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d + create mode 100644 test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f + create mode 100644 test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/ba0dae6243cc9fa2890df40a625721fdbea5c94ca6da897acdd814d710149770 + create mode 100644 test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/base + create mode 100644 test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/deviceset-metadata + create mode 100644 test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/transaction-metadata + create mode 100644 test/image/oci/storage/layers/devmapper/driver_devmapper_ut.cc + create mode 100644 test/mocks/libdevmapper_mock.cc + create mode 100644 test/mocks/libdevmapper_mock.h + +diff --git a/test/image/oci/storage/layers/CMakeLists.txt b/test/image/oci/storage/layers/CMakeLists.txt +index 413a8b38..e1c76453 100644 +--- a/test/image/oci/storage/layers/CMakeLists.txt ++++ b/test/image/oci/storage/layers/CMakeLists.txt +@@ -1,5 +1,7 @@ + project(iSulad_UT) + ++add_subdirectory(devmapper) ++ + # storage_driver_ut + SET(DRIVER_EXE storage_driver_ut) + +diff --git a/test/image/oci/storage/layers/devmapper/CMakeLists.txt b/test/image/oci/storage/layers/devmapper/CMakeLists.txt +new file mode 100644 +index 00000000..f98de1a8 +--- /dev/null ++++ b/test/image/oci/storage/layers/devmapper/CMakeLists.txt +@@ -0,0 +1,71 @@ ++project(iSulad_UT) ++ ++# driver_devmapper_ut ++SET(DRIVER_DEVMAPPER_EXE driver_devmapper_ut) ++ ++add_executable(${DRIVER_DEVMAPPER_EXE} ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_regex.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_verify.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_array.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_string.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_convert.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_file.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_fs.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/util_atomic.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_base64.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/utils_timestamp.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/path.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/map/map.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/cutils/map/rb_tree.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/buffer/buffer.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/tar/util_archive.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/tar/util_gzip.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/sha256/sha256.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/common/err_msg.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/common/selinux_label.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/metadata_store.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/wrapper_devmapper.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../mocks/libdevmapper_mock.cc ++ driver_devmapper_ut.cc) ++ ++target_include_directories(${DRIVER_DEVMAPPER_EXE} PUBLIC ++ ${GTEST_INCLUDE_DIR} ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../include ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/common ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/tar ++ ${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/console ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/buffer ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/config ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/common ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/api ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage ++ ${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/devmapper ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2 ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/remote_layer_support ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/quota ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../mocks ++ ) ++ ++set_target_properties(${DRIVER_DEVMAPPER_EXE} PROPERTIES LINK_FLAGS "-Wl,--wrap,util_exec_cmd -Wl,--wrap,util_mount -Wl,--wrap,umount2") ++ ++target_link_libraries(${DRIVER_DEVMAPPER_EXE} ++ ${GTEST_BOTH_LIBRARIES} ++ ${GMOCK_LIBRARY} ++ ${GMOCK_MAIN_LIBRARY} ++ ${CMAKE_THREAD_LIBS_INIT} ++ ${ISULA_LIBUTILS_LIBRARY} ++ ${LIBTAR_LIBRARY} ++ -lcrypto -lyajl -larchive ${SELINUX_LIBRARY} -lz -lcap) ++ ++add_test(NAME ${DRIVER_DEVMAPPER_EXE} COMMAND ${DRIVER_DEVMAPPER_EXE} --gtest_output=xml:${DRIVER_DEVMAPPER_EXE}-Results.xml) ++set_tests_properties(${DRIVER_DEVMAPPER_EXE} PROPERTIES TIMEOUT 120) +diff --git a/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d +new file mode 100644 +index 00000000..f51ae926 +--- /dev/null ++++ b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d +@@ -0,0 +1,6 @@ ++{ ++ "hash": "068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d", ++ "device_id": 6, ++ "size": 10737418240, ++ "transaction_id": 8 ++} +diff --git a/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f +new file mode 100644 +index 00000000..de727a79 +--- /dev/null ++++ b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f +@@ -0,0 +1,6 @@ ++{ ++ "hash": "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f", ++ "device_id": 4, ++ "size": 10737418240, ++ "transaction_id": 4 ++} +diff --git a/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/ba0dae6243cc9fa2890df40a625721fdbea5c94ca6da897acdd814d710149770 b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/ba0dae6243cc9fa2890df40a625721fdbea5c94ca6da897acdd814d710149770 +new file mode 100644 +index 00000000..e1e8988e +--- /dev/null ++++ b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/ba0dae6243cc9fa2890df40a625721fdbea5c94ca6da897acdd814d710149770 +@@ -0,0 +1,6 @@ ++{ ++ "hash": "ba0dae6243cc9fa2890df40a625721fdbea5c94ca6da897acdd814d710149770", ++ "device_id": 2, ++ "size": 10737418240, ++ "transaction_id": 2 ++} +diff --git a/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/base b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/base +new file mode 100644 +index 00000000..2412113d +--- /dev/null ++++ b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/base +@@ -0,0 +1,7 @@ ++{ ++ "hash": "base", ++ "device_id": 1, ++ "size": 10737418240, ++ "transaction_id": 1, ++ "initialized": true ++} +diff --git a/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/deviceset-metadata b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/deviceset-metadata +new file mode 100644 +index 00000000..94f7a6a3 +--- /dev/null ++++ b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/deviceset-metadata +@@ -0,0 +1,5 @@ ++{ ++ "next_device_id": 7, ++ "BaseDeviceFilesystem": "ext4", ++ "BaseDeviceUUID": "4fa22307-0c88-4fa4-8f16-a9459e9cbc4a" ++} +diff --git a/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/transaction-metadata b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/transaction-metadata +new file mode 100644 +index 00000000..a011249a +--- /dev/null ++++ b/test/image/oci/storage/layers/devmapper/data/devicemapper/metadata/transaction-metadata +@@ -0,0 +1,5 @@ ++{ ++ "open_transaction_id": 8, ++ "device_hash": "068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d", ++ "device_id": 6 ++} +diff --git a/test/image/oci/storage/layers/devmapper/driver_devmapper_ut.cc b/test/image/oci/storage/layers/devmapper/driver_devmapper_ut.cc +new file mode 100644 +index 00000000..59e53f97 +--- /dev/null ++++ b/test/image/oci/storage/layers/devmapper/driver_devmapper_ut.cc +@@ -0,0 +1,283 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: jikai ++ * Create: 2023-11-22 ++ * Description: provide oci storage driver unit test for devmapper ++ ******************************************************************************/ ++ ++#include ++#include ++ ++#include "driver_devmapper.h" ++#include "mock.h" ++#include "path.h" ++#include "utils.h" ++#include "libdevmapper_mock.h" ++ ++using ::testing::Invoke; ++using ::testing::NiceMock; ++using ::testing::Return; ++using ::testing::_; ++ ++extern "C" { ++ DECLARE_WRAPPER_V(util_exec_cmd, bool, (exec_func_t cb_func, void *args, const char *stdin_msg, char **stdout_msg, char **stderr_msg)); ++ DEFINE_WRAPPER_V(util_exec_cmd, bool, (exec_func_t cb_func, void *args, const char *stdin_msg, char **stdout_msg, char **stderr_msg), (cb_func, args, stdin_msg, stdout_msg, stderr_msg)); ++ ++ DECLARE_WRAPPER(util_mount, int, (const char *src, const char *dst, const char *mtype, const char *mntopts)); ++ DEFINE_WRAPPER(util_mount, int, (const char *src, const char *dst, const char *mtype, const char *mntopts), (src, dst, mtype, mntopts)); ++ ++ DECLARE_WRAPPER(umount2, int, (const char *__special_file, int __flags)); ++ DEFINE_WRAPPER(umount2, int, (const char *__special_file, int __flags), (__special_file, __flags)); ++} ++ ++static std::string GetDirectory() ++{ ++ char abs_path[PATH_MAX] { 0x00 }; ++ int ret = readlink("/proc/self/exe", abs_path, sizeof(abs_path)); ++ if (ret < 0 || static_cast(ret) >= sizeof(abs_path)) { ++ return ""; ++ } ++ ++ for (int i { ret }; i >= 0; --i) { ++ if (abs_path[i] == '/') { ++ abs_path[i + 1] = '\0'; ++ break; ++ } ++ } ++ ++ return static_cast(abs_path) + "../../../../../../../test/image/oci/storage/layers/devmapper"; ++} ++ ++static bool invokeUtilExecCmd(exec_func_t cb_func, void *args, const char *stdin_msg, char **stdout_msg, char **stderr_msg) ++{ ++ if (cb_func == nullptr || args == nullptr || stdout_msg == nullptr || stderr_msg == nullptr) { ++ return false; ++ } ++ ++ char **tmp_args = static_cast(args); ++ ++ if (util_array_len((const char **)tmp_args) < 1) { ++ return false; ++ } ++ ++ if (strcmp(tmp_args[0], "blkid") == 0) { ++ *stdout_msg = util_strdup_s("4fa22307-0c88-4fa4-8f16-a9459e9cbc4a"); ++ } ++ return true; ++} ++ ++static struct dm_task *invokeDMTaskCreate(int type) { ++ return static_cast(util_common_calloc_s(sizeof(0))); ++} ++ ++static void invokeDMTaskDestroy(struct dm_task *task) { ++ free(task); ++ return; ++} ++ ++static int invokeDMTaskGetDriverVersion(struct dm_task *task, char *version, size_t size) { ++ if (task == nullptr || version == nullptr || strncpy(version, "4.27.0", size) == NULL) { ++ return 0; ++ } ++ ++ return 1; ++} ++ ++static int invokeDMTaskGetInfo(struct dm_task *task, struct dm_info *dmi) { ++ if (task == nullptr || dmi == nullptr) { ++ return 0; ++ } ++ ++ dmi->exists = 1; ++ return 1; ++} ++ ++static void *invokeDMGetNextTarget(struct dm_task *task, void *next, uint64_t *start, uint64_t *length, ++ char **target_type, char **params) { ++ static char type[] = "thin-pool"; ++ static char par[] = "0 0/1024 0/1024"; ++ if (target_type) { ++ *target_type = type; ++ } ++ if (params) { ++ *params = par; ++ } ++ return nullptr; ++} ++ ++class DriverDevmapperUnitTest : public testing::Test { ++protected: ++ void SetUp() override ++ { ++ MockLibdevmapper_SetMock(&m_libdevmapper_mock); ++ std::string isulad_dir { "/tmp/isulad/" }; ++ mkdir(isulad_dir.c_str(), 0755); ++ std::string root_dir = isulad_dir + "data"; ++ std::string run_dir = isulad_dir + "data/run"; ++ std::string data_dir = GetDirectory() + "/data"; ++ std::string driver_home = root_dir + "/devicemapper"; ++ ++ ASSERT_STRNE(util_clean_path(data_dir.c_str(), data_path, sizeof(data_path)), nullptr); ++ std::string cp_command = "cp -r " + std::string(data_path) + " " + isulad_dir; ++ ASSERT_EQ(system(cp_command.c_str()), 0); ++ ++ char **driver_opts = static_cast(util_common_calloc_s(3 * sizeof(char *))); ++ driver_opts[0] = strdup("dm.thinpooldev=/dev/mapper/isulad0-thinpool"); ++ driver_opts[1] = strdup("dm.fs=ext4"); ++ driver_opts[2] = strdup("dm.min_free_space=10%"); ++ int driver_opts_len = 3; ++ ++ ASSERT_EQ(devmapper_init(&driver, nullptr, (const char **)driver_opts, driver_opts_len), -1); ++ ++ EXPECT_CALL(m_libdevmapper_mock, DMTaskCreate(_)).WillRepeatedly(Invoke(invokeDMTaskCreate)); ++ EXPECT_CALL(m_libdevmapper_mock, DMTaskSetMessage(_, _)).WillRepeatedly(Return(1)); ++ EXPECT_CALL(m_libdevmapper_mock, DMTaskSetSector(_, _)).WillRepeatedly(Return(1)); ++ EXPECT_CALL(m_libdevmapper_mock, DMTaskSetAddNode(_, _)).WillRepeatedly(Return(1)); ++ EXPECT_CALL(m_libdevmapper_mock, DMTaskAddTarget(_, _, _, _, _)).WillRepeatedly(Return(1)); ++ EXPECT_CALL(m_libdevmapper_mock, DMTaskSetName(_, _)).WillRepeatedly(Return(1)); ++ EXPECT_CALL(m_libdevmapper_mock, DMTaskRun(_)).WillRepeatedly(Return(1)); ++ EXPECT_CALL(m_libdevmapper_mock, DMTaskDestroy(_)).WillRepeatedly(Invoke(invokeDMTaskDestroy)); ++ EXPECT_CALL(m_libdevmapper_mock, DMTaskGetInfo(_, _)).WillRepeatedly(Invoke(invokeDMTaskGetInfo)); ++ EXPECT_CALL(m_libdevmapper_mock, DMGetNextTarget(_, _, _, _, _, _)).WillRepeatedly(Invoke(invokeDMGetNextTarget)); ++ EXPECT_CALL(m_libdevmapper_mock, DMTaskSetCookie(_, _, _)).WillRepeatedly(Return(1)); ++ EXPECT_CALL(m_libdevmapper_mock, DMUdevWait(_)).WillRepeatedly(Return(1)); ++ EXPECT_CALL(m_libdevmapper_mock, DMUdevComplete(_)).WillRepeatedly(Return(1)); ++ EXPECT_CALL(m_libdevmapper_mock, DMTaskDeferredRemove(_)).WillRepeatedly(Return(1)); ++ ++ ++ char *names = static_cast(util_common_calloc_s(sizeof(struct dm_names) + strlen("isulad0-pool") + 1)); ++ struct dm_names *dname = (struct dm_names *)names; ++ dname->dev = 1; ++ dname->next = 0; ++ strcpy(names + sizeof(struct dm_names), "isulad0-pool"); ++ EXPECT_CALL(m_libdevmapper_mock, DMTaskGetNames(_)).WillOnce(Return(dname)); ++ EXPECT_CALL(m_libdevmapper_mock, DMSetDevDir(_)).WillOnce(Return(1)); ++ EXPECT_CALL(m_libdevmapper_mock, DMTaskGetDriverVersion(_, _, _)).WillOnce(Invoke(invokeDMTaskGetDriverVersion)); ++ EXPECT_CALL(m_libdevmapper_mock, DMUdevGetSyncSupport()).WillOnce(Return(1)); ++ ++ MOCK_SET_V(util_exec_cmd, invokeUtilExecCmd); ++ ++ ASSERT_EQ(devmapper_init(&driver, driver_home.c_str(), (const char **)driver_opts, driver_opts_len), 0); ++ MOCK_CLEAR(util_exec_cmd); ++ ++ util_free_array_by_len(driver_opts, driver_opts_len); ++ free(names); ++ } ++ ++ void TearDown() override ++ { ++ MockLibdevmapper_SetMock(nullptr); ++ std::string rm_command = "rm -rf /tmp/isulad/"; ++ ASSERT_EQ(system(rm_command.c_str()), 0); ++ } ++ ++ NiceMock m_libdevmapper_mock; ++ char data_path[PATH_MAX] = { 0x00 }; ++ graphdriver driver = {.ops = nullptr, .name = "devicemapper", }; ++}; ++ ++TEST_F(DriverDevmapperUnitTest, test_devmapper_layer_exists) ++{ ++ std::string id { "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f" }; ++ std::string incorrectId { "eb29745b8228e1e97c01b1d5c2554a319c00a94d8dd5746a3904222ad65a13f8" }; ++ ASSERT_TRUE(devmapper_layer_exist(id.c_str(), &driver)); ++ ASSERT_FALSE(devmapper_layer_exist(incorrectId.c_str(), &driver)); ++} ++ ++TEST_F(DriverDevmapperUnitTest, test_devmapper_create_rw) ++{ ++ std::string id { "eb29745b8228e1e97c01b1d5c2554a319c00a94d8dd5746a3904222ad65a13f8" }; ++ struct driver_create_opts *create_opts; ++ ++ create_opts = (struct driver_create_opts *)util_common_calloc_s(sizeof(struct driver_create_opts)); ++ ASSERT_NE(create_opts, nullptr); ++ ++ create_opts->storage_opt = static_cast(util_common_calloc_s(sizeof(json_map_string_string))); ++ ASSERT_NE(create_opts->storage_opt, nullptr); ++ create_opts->storage_opt->keys = static_cast(util_common_calloc_s(sizeof(char *))); ++ create_opts->storage_opt->values = static_cast(util_common_calloc_s(sizeof(char *))); ++ create_opts->storage_opt->keys[0] = strdup("size"); ++ create_opts->storage_opt->values[0] = strdup("10G"); ++ create_opts->storage_opt->len = 1; ++ ++ ASSERT_EQ(devmapper_create_rw(id.c_str(), nullptr, &driver, create_opts), 0); ++ ASSERT_TRUE(devmapper_layer_exist(id.c_str(), &driver)); ++} ++ ++TEST_F(DriverDevmapperUnitTest, test_devmapper_mount_layer) ++{ ++ std::string id { "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f" }; ++ std::string merged_dir = "/tmp/isulad/data/devicemapper/mnt/" + id + "/rootfs"; ++ struct driver_mount_opts *mount_opts = nullptr; ++ char* mount_dir = nullptr; ++ ++ MOCK_SET(util_mount, 0); ++ mount_dir = devmapper_mount_layer(id.c_str(), &driver, mount_opts); ++ ASSERT_STREQ(mount_dir, merged_dir.c_str()); ++ MOCK_CLEAR(util_mount); ++ ++ MOCK_SET(umount2, 0); ++ ASSERT_EQ(devmapper_umount_layer(id.c_str(), &driver), 0); ++ MOCK_CLEAR(umount2); ++ free(mount_dir); ++ mount_dir = nullptr; ++ ++ mount_opts = static_cast(util_common_calloc_s(sizeof(struct driver_mount_opts))); ++ ASSERT_NE(mount_opts, nullptr); ++ mount_opts->options = static_cast(util_common_calloc_s(1 * sizeof(char *))); ++ mount_opts->options[0] = strdup("ro"); ++ mount_opts->options_len = 1; ++ ++ MOCK_SET(util_mount, 0); ++ mount_dir = devmapper_mount_layer(id.c_str(), &driver, mount_opts); ++ ASSERT_STREQ(mount_dir, merged_dir.c_str()); ++ MOCK_CLEAR(util_mount); ++ ++ MOCK_SET(umount2, 0); ++ ASSERT_EQ(devmapper_umount_layer(id.c_str(), &driver), 0); ++ MOCK_CLEAR(umount2); ++ free(mount_opts->mount_label); ++ util_free_array_by_len(mount_opts->options, mount_opts->options_len); ++ free(mount_opts); ++ free(mount_dir); ++} ++ ++TEST_F(DriverDevmapperUnitTest, test_devmapper_get_layer_metadata) ++{ ++ std::string id { "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f" }; ++ json_map_string_string *map_info = static_cast(util_common_calloc_s(sizeof(json_map_string_string))); ++ ++ ASSERT_EQ(devmapper_get_layer_metadata(id.c_str(), &driver, map_info), 0); ++ ASSERT_EQ(map_info->len, 4); ++ ASSERT_STREQ(map_info->keys[0], "DeviceId"); ++ ASSERT_STREQ(map_info->values[0], "4"); ++ ASSERT_STREQ(map_info->keys[1], "DeviceSize"); ++ ASSERT_STREQ(map_info->values[1], "10737418240"); ++ ASSERT_STREQ(map_info->keys[2], "DeviceName"); ++ ASSERT_STREQ(map_info->keys[3], "MergedDir"); ++ ASSERT_STREQ(map_info->values[3], "/tmp/isulad/data/devicemapper/mnt/3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f/rootfs"); ++ ++ free_json_map_string_string(map_info); ++} ++ ++TEST_F(DriverDevmapperUnitTest, test_devmapper_get_driver_status) ++{ ++ struct graphdriver_status *status = static_cast(util_common_calloc_s(sizeof(struct graphdriver_status))); ++ ++ EXPECT_CALL(m_libdevmapper_mock, DMUdevGetSyncSupport()).WillOnce(Return(1)); ++ ++ ASSERT_EQ(devmapper_get_driver_status(&driver, status), 0); ++ ASSERT_STREQ(status->driver_name, "devicemapper"); ++ free(status->driver_name); ++ free(status->backing_fs); ++ free(status->status); ++ free(status); ++} +diff --git a/test/mocks/libdevmapper_mock.cc b/test/mocks/libdevmapper_mock.cc +new file mode 100644 +index 00000000..7d6c8024 +--- /dev/null ++++ b/test/mocks/libdevmapper_mock.cc +@@ -0,0 +1,191 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: jikai ++ * Create: 2023-11-22 ++ * Description: provide lib device mapper mock ++ ******************************************************************************/ ++ ++#include "libdevmapper_mock.h" ++ ++namespace { ++MockLibdevmapper *g_libdevmapper_mock = nullptr; ++} ++ ++void MockLibdevmapper_SetMock(MockLibdevmapper* mock) ++{ ++ g_libdevmapper_mock = mock; ++} ++ ++struct dm_task *dm_task_create(int type) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMTaskCreate(type); ++ } ++ return nullptr; ++} ++ ++int dm_task_set_message(struct dm_task *dmt, const char *msg) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMTaskSetMessage(dmt, msg); ++ } ++ return 0; ++} ++ ++int dm_task_set_sector(struct dm_task *dmt, uint64_t sector) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMTaskSetSector(dmt, sector); ++ } ++ return 0; ++} ++ ++int dm_task_set_add_node(struct dm_task *dmt, dm_add_node_t add_node) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMTaskSetAddNode(dmt, add_node); ++ } ++ return 0; ++} ++ ++int dm_task_add_target(struct dm_task *dmt, uint64_t start, uint64_t size, const char *ttype, const char *params) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMTaskAddTarget(dmt, start, size, ttype, params); ++ } ++ return 0; ++} ++ ++int dm_set_dev_dir(const char *dir) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMSetDevDir(dir); ++ } ++ return 0; ++} ++ ++int dm_task_set_name(struct dm_task *dmt, const char *name) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMTaskSetName(dmt, name); ++ } ++ return 0; ++} ++ ++int dm_task_run(struct dm_task *dmt) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMTaskRun(dmt); ++ } ++ return 0; ++} ++ ++int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMTaskGetDriverVersion(dmt, version, size); ++ } ++ return 0; ++} ++ ++void dm_task_destroy(struct dm_task *dmt) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ g_libdevmapper_mock->DMTaskDestroy(dmt); ++ } ++} ++ ++int dm_get_library_version(char *version, size_t size) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMGetLibraryVersion(version, size); ++ } ++ return 0; ++} ++ ++int dm_task_get_info(struct dm_task *dmt, struct dm_info *info) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMTaskGetInfo(dmt, info); ++ } ++ return 0; ++} ++ ++void *dm_get_next_target(struct dm_task *dmt, void *next, uint64_t *start, uint64_t *length, ++ char **target_type, char **params) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMGetNextTarget(dmt, next, start, length, target_type, params); ++ } ++ return nullptr; ++} ++ ++int dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie, uint16_t flags) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMTaskSetCookie(dmt, cookie, flags); ++ } ++ return 0; ++} ++ ++int dm_udev_wait(uint32_t cookie) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMUdevWait(cookie); ++ } ++ return 0; ++} ++ ++int dm_udev_complete(uint32_t cookie) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMUdevComplete(cookie); ++ } ++ return 0; ++} ++ ++int dm_task_deferred_remove(struct dm_task *dmt) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMTaskDeferredRemove(dmt); ++ } ++ return 0; ++} ++ ++struct dm_names *dm_task_get_names(struct dm_task *dmt) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMTaskGetNames(dmt); ++ } ++ return nullptr; ++} ++ ++int dm_udev_get_sync_support(void) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ return g_libdevmapper_mock->DMUdevGetSyncSupport(); ++ } ++ return 0; ++} ++ ++void dm_udev_set_sync_support(int sync_with_udev) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ g_libdevmapper_mock->DMUdevSetSyncSupport(sync_with_udev); ++ } ++} ++ ++void dm_log_with_errno_init(void log_cb(int level, const char *file, int line, int dm_errno_or_class, const char *f, ...)) ++{ ++ if (g_libdevmapper_mock != nullptr) { ++ g_libdevmapper_mock->DMLogWithErrnoInit(log_cb); ++ } ++} +diff --git a/test/mocks/libdevmapper_mock.h b/test/mocks/libdevmapper_mock.h +new file mode 100644 +index 00000000..53c5ad4b +--- /dev/null ++++ b/test/mocks/libdevmapper_mock.h +@@ -0,0 +1,52 @@ ++/****************************************************************************** ++ * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. ++ * iSulad licensed under the Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR ++ * PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ * Author: jikai ++ * Create: 2023-11-22 ++ * Description: provide lib device mapper mock ++ ******************************************************************************/ ++ ++#ifndef _ISULAD_TEST_MOCKS_DEVMAPPER_MOCK_H ++#define _ISULAD_TEST_MOCKS_DEVMAPPER_MOCK_H ++ ++#include ++ ++#include ++ ++class MockLibdevmapper { ++public: ++ virtual ~MockLibdevmapper() = default; ++ MOCK_METHOD1(DMTaskCreate, struct dm_task*(int type)); ++ MOCK_METHOD2(DMTaskSetMessage, int(struct dm_task *dmt, const char *msg)); ++ MOCK_METHOD2(DMTaskSetSector, int(struct dm_task *dmt, uint64_t sector)); ++ MOCK_METHOD2(DMTaskSetAddNode, int(struct dm_task *dmt, dm_add_node_t add_node)); ++ MOCK_METHOD5(DMTaskAddTarget, int(struct dm_task *dmt, uint64_t start, uint64_t size, const char *ttype, const char *params)); ++ MOCK_METHOD1(DMSetDevDir, int(const char *dir)); ++ MOCK_METHOD2(DMTaskSetName, int(struct dm_task *dmt, const char *name)); ++ MOCK_METHOD1(DMTaskRun, int(struct dm_task *dmt)); ++ MOCK_METHOD3(DMTaskGetDriverVersion, int(struct dm_task *dmt, char *version, size_t size)); ++ MOCK_METHOD1(DMTaskDestroy, void(struct dm_task *dmt)); ++ MOCK_METHOD2(DMGetLibraryVersion, int(char *version, size_t size)); ++ MOCK_METHOD2(DMTaskGetInfo, int(struct dm_task *dmt, struct dm_info *info)); ++ MOCK_METHOD6(DMGetNextTarget, void*(struct dm_task *dmt, void *next, uint64_t *start, uint64_t *length, ++ char **target_type, char **params)); ++ MOCK_METHOD3(DMTaskSetCookie, int(struct dm_task *dmt, uint32_t *cookie, uint16_t flags)); ++ MOCK_METHOD1(DMUdevWait, int(uint32_t cookie)); ++ MOCK_METHOD1(DMUdevComplete, int(uint32_t cookie)); ++ MOCK_METHOD1(DMTaskDeferredRemove, int(struct dm_task *dmt)); ++ MOCK_METHOD1(DMTaskGetNames, struct dm_names *(struct dm_task *dmt)); ++ MOCK_METHOD0(DMUdevGetSyncSupport, int(void)); ++ MOCK_METHOD1(DMUdevSetSyncSupport, void(int sync_with_udev)); ++ MOCK_METHOD1(DMLogWithErrnoInit, void(void log_cb(int level, const char *file, int line, int dm_errno_or_class, const char *f, ...))); ++}; ++ ++void MockLibdevmapper_SetMock(MockLibdevmapper* mock); ++ ++#endif +-- +2.42.0 + diff --git a/0033-2275-bugfix-for-rt_lcr_rebuild_config.patch b/0033-2275-bugfix-for-rt_lcr_rebuild_config.patch new file mode 100644 index 0000000..ec42563 --- /dev/null +++ b/0033-2275-bugfix-for-rt_lcr_rebuild_config.patch @@ -0,0 +1,46 @@ +From fa7356538c7f747a81aa3d0a511a662ee4345afe Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Fri, 24 Nov 2023 08:33:45 +0000 +Subject: [PATCH 33/64] !2275 bugfix for rt_lcr_rebuild_config * bugfix for + rt_lcr_rebuild_config + +--- + src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c +index 8f7211d7..44ecab5a 100644 +--- a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c ++++ b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c +@@ -777,6 +777,7 @@ int rt_lcr_rebuild_config(const char *name, const char *runtime, const rt_rebuil + { + int ret = -1; + int nret = 0; ++ bool rebuild_success = false; + char config_file[PATH_MAX] = { 0 }; + char bak_config_file[PATH_MAX] = { 0 }; + char oci_config_file[PATH_MAX] = { 0 }; +@@ -825,8 +826,8 @@ int rt_lcr_rebuild_config(const char *name, const char *runtime, const rt_rebuil + goto out; + } + +- nret = engine_ops->engine_create_op(name, params->rootpath, (void *)oci_spec); +- if (nret != 0) { ++ rebuild_success = engine_ops->engine_create_op(name, params->rootpath, (void *)oci_spec); ++ if (!rebuild_success) { + // delete the invalid config file to prevent rename failed + if (util_fileself_exists(config_file) && util_path_remove(config_file) != 0) { + WARN("Failed to remove bak_config_file for container %s", name); +@@ -835,7 +836,8 @@ int rt_lcr_rebuild_config(const char *name, const char *runtime, const rt_rebuil + WARN("Failed to rename backup old config to config for container %s", name); + } + } +- ret = nret != 0 ? -1 : 0; ++ ret = rebuild_success ? 0 : -1; ++ + out: + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { + engine_ops->engine_clear_errmsg_op(); +-- +2.42.0 + diff --git a/0034-2277-remove-shim-v2-format-error-log.patch b/0034-2277-remove-shim-v2-format-error-log.patch new file mode 100644 index 0000000..1573b9e --- /dev/null +++ b/0034-2277-remove-shim-v2-format-error-log.patch @@ -0,0 +1,25 @@ +From fe03c12676b8a48a2aede2d177f2cbcbdd68f930 Mon Sep 17 00:00:00 2001 +From: jake +Date: Sat, 25 Nov 2023 03:34:01 +0000 +Subject: [PATCH 34/64] !2277 remove shim v2 format error log * remove shim v2 + format error log + +--- + src/daemon/modules/runtime/shim/shim_rt_ops.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/daemon/modules/runtime/shim/shim_rt_ops.c b/src/daemon/modules/runtime/shim/shim_rt_ops.c +index 1bc9dc54..5066f804 100644 +--- a/src/daemon/modules/runtime/shim/shim_rt_ops.c ++++ b/src/daemon/modules/runtime/shim/shim_rt_ops.c +@@ -115,7 +115,6 @@ bool is_valid_v2_runtime(const char* name) + + parts_len = util_array_len((const char **)parts); + if (!(parts_len == 4 && strcmp(parts[0], "io") == 0 && strcmp(parts[1], "containerd") == 0)) { +- ERROR("ShimV2 runtime format is wrong"); + util_free_array(parts); + return false; + } +-- +2.42.0 + diff --git a/0035-2276-bugfix-for-integration_check.sh.patch b/0035-2276-bugfix-for-integration_check.sh.patch new file mode 100644 index 0000000..c870e52 --- /dev/null +++ b/0035-2276-bugfix-for-integration_check.sh.patch @@ -0,0 +1,26 @@ +From a2c565705f80f787e50ffc15db38ba367f517eb2 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Sat, 25 Nov 2023 03:34:50 +0000 +Subject: [PATCH 35/64] !2276 bugfix for integration_check.sh * bugfix for + integration_check.sh + +--- + CI/test_cases/image_cases/integration_check.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CI/test_cases/image_cases/integration_check.sh b/CI/test_cases/image_cases/integration_check.sh +index e43369e3..6ec3ab52 100755 +--- a/CI/test_cases/image_cases/integration_check.sh ++++ b/CI/test_cases/image_cases/integration_check.sh +@@ -65,7 +65,7 @@ function test_image_info() + echo "xxx:11" >> ${change_file} + + sed -i 's#image-layer-check": false#image-layer-check": true#g' /etc/isulad/daemon.json +- pkill -9 isulad ++ kill -9 $(pidof isulad) + start_isulad_with_valgrind + + isula ps -a | grep ${cid} +-- +2.42.0 + diff --git a/0036-modify-create_network.sh-for-default-runtime-changed.patch b/0036-modify-create_network.sh-for-default-runtime-changed.patch new file mode 100644 index 0000000..40e9feb --- /dev/null +++ b/0036-modify-create_network.sh-for-default-runtime-changed.patch @@ -0,0 +1,40 @@ +From e422c6cf725240dea80e1c51ba21cae8ee6641c6 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Sat, 25 Nov 2023 18:21:56 +0800 +Subject: [PATCH 36/64] modify create_network.sh for default runtime changed + +Signed-off-by: zhongtao +--- + CI/test_cases/container_cases/create_network.sh | 2 +- + CI/test_cases/helpers.sh | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/CI/test_cases/container_cases/create_network.sh b/CI/test_cases/container_cases/create_network.sh +index 470bda70..5bafbc60 100755 +--- a/CI/test_cases/container_cases/create_network.sh ++++ b/CI/test_cases/container_cases/create_network.sh +@@ -37,7 +37,7 @@ function test_network_param() + + msg_info "${test} starting..." + +- root="`isula info | grep 'iSulad Root Dir' | awk -F ':' '{print $2}'`/engines/lcr" ++ root="`isula info | grep 'iSulad Root Dir' | awk -F ':' '{print $2}'`/engines/$DEFAULT_RUNTIME" + + isula pull ${image} + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to pull image: ${image}" && return ${FAILURE} +diff --git a/CI/test_cases/helpers.sh b/CI/test_cases/helpers.sh +index f3eeb54d..c5eba8a2 100755 +--- a/CI/test_cases/helpers.sh ++++ b/CI/test_cases/helpers.sh +@@ -29,6 +29,8 @@ ISULAD_RUN_ROOT_PATH="/var/run/isulad" + + RUNTIME_LIST=(lcr runc) + ++DEFAULT_RUNTIME=runc ++ + testcase_data="/tmp/testcases_data" + + enable_native_network=0 +-- +2.42.0 + diff --git a/0037-modify-the-container-runtime-when-running-embedded.s.patch b/0037-modify-the-container-runtime-when-running-embedded.s.patch new file mode 100644 index 0000000..7ba3583 --- /dev/null +++ b/0037-modify-the-container-runtime-when-running-embedded.s.patch @@ -0,0 +1,141 @@ +From 8e4b6eceeb117fc90b5b638329f8888e43d3f442 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Mon, 27 Nov 2023 17:21:15 +0800 +Subject: [PATCH 37/64] modify the container runtime when running embedded.sh + +Signed-off-by: zhongtao +--- + CI/test_cases/image_cases/embedded.sh | 30 +++++++++++++-------------- + 1 file changed, 15 insertions(+), 15 deletions(-) + +diff --git a/CI/test_cases/image_cases/embedded.sh b/CI/test_cases/image_cases/embedded.sh +index cdc75e50..a1d4c37a 100755 +--- a/CI/test_cases/image_cases/embedded.sh ++++ b/CI/test_cases/image_cases/embedded.sh +@@ -81,14 +81,14 @@ function test_run_image() + { + local ret=0 + +- isula run -t -n embedded_test1 nonexistentname1:v1 /bin/sh ++ isula run --runtime lcr -t -n embedded_test1 nonexistentname1:v1 /bin/sh + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - run nonexistent image should failed" && ((ret++)) + + isula load -i "$embedded_manifest" -t embedded + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - load embedded image failed" && ((ret++)) + + # run container based on embedded image +- isula run --name embedded_test1 test:v1 ls /home/home/home ++ isula run --runtime lcr --name embedded_test1 test:v1 ls /home/home/home + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - run embedded image failed" && ((ret++)) + + # delete container based on embedded image +@@ -96,7 +96,7 @@ function test_run_image() + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - delete container based on embedded image failed" && ((ret++)) + + # test image's env +- isula run --name embedded_test1 test:v1 /bin/sh -c "echo \$c | grep \"d e\"" ++ isula run --runtime lcr --name embedded_test1 test:v1 /bin/sh -c "echo \$c | grep \"d e\"" + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - test image's env failed" && ((ret++)) + + # delete container based on embedded image +@@ -119,7 +119,7 @@ function test_mount() + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - load embedded imagefailed" && ((ret++)) + + # run --mount +- isula run --mount type=bind,src="$embedded_basedir",dst=/usr,ro=true,bind-propagation=rprivate --name embedded_test2 test:v1 true ++ isula run --runtime lcr --mount type=bind,src="$embedded_basedir",dst=/usr,ro=true,bind-propagation=rprivate --name embedded_test2 test:v1 true + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - run --mount failed" && ((ret++)) + + testcontainer embedded_test2 exited +@@ -127,25 +127,25 @@ function test_mount() + isula rm embedded_test2 + + # test invalid mode +- isula run --mount type=bind,src="$embedded_basedir",dst=/usr,ro=invalid --name embedded_test2 test:v1 true ++ isula run --runtime lcr --mount type=bind,src="$embedded_basedir",dst=/usr,ro=invalid --name embedded_test2 test:v1 true + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - invalid mode should failed" && ((ret++)) + + isula rm embedded_test2 + + # test invalid bind propagation mode +- isula run --mount type=bind,src="$embedded_basedir",dst=/usr,bind-propagation=invalid --name embedded_test2 test:v1 true ++ isula run --runtime lcr --mount type=bind,src="$embedded_basedir",dst=/usr,bind-propagation=invalid --name embedded_test2 test:v1 true + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - invalid bind propagation mode should failed" && ((ret++)) + + isula rm embedded_test2 + + # test source not exist +- isula run --mount type=bind,src=abcdefg/notexist,dst=/usr --name embedded_test2 test:v1 true ++ isula run --runtime lcr --mount type=bind,src=abcdefg/notexist,dst=/usr --name embedded_test2 test:v1 true + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - invalid source not exist should failed" && ((ret++)) + + isula rm embedded_test2 + + # test source not a regular file +- isula run --mount type=squashfs,src=/tmp,dst=/usr --name embedded_test2 test:v1 true ++ isula run --runtime lcr --mount type=squashfs,src=/tmp,dst=/usr --name embedded_test2 test:v1 true + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - source not a regular file should failed" && ((ret++)) + + isula rm embedded_test2 +@@ -153,7 +153,7 @@ function test_mount() + # test path //tmp/test + mkdir -p /tmp/test_mount + mkdir -p /tmp/test_mount1/test +- isula run -v /tmp/test_mount:/tmp --mount type=bind,src=/tmp/test_mount1,dst=//tmp/test_mount1,ro=true,bind-propagation=rprivate --name embedded_test2 test:v1 ls /tmp/test_mount1/test ++ isula run --runtime lcr -v /tmp/test_mount:/tmp --mount type=bind,src=/tmp/test_mount1,dst=//tmp/test_mount1,ro=true,bind-propagation=rprivate --name embedded_test2 test:v1 ls /tmp/test_mount1/test + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - test path //tmp/test failed" && ((ret++)) + + isula rm embedded_test2 +@@ -186,7 +186,7 @@ function test_query_image() + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - inspect nonexist item should failed" && ((ret++)) + + # test inspect container, it should conatainer image info +- isula run --name embedded_inspect test:v1 ls /home/home/home ++ isula run --runtime lcr --name embedded_inspect test:v1 ls /home/home/home + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - run container for inspect failed" && ((ret++)) + + isula inspect -f '{{json .Image}}' embedded_inspect +@@ -437,19 +437,19 @@ function test_entrypoint() + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - load embedded image failed" && ((ret++)) + + # test image's entrypoint +- isula run --name embedded_entrypoint1 test:v1 ++ isula run --runtime lcr --name embedded_entrypoint1 test:v1 + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - test image's entrypoint failed" && ((ret++)) + + isula rm embedded_entrypoint1 + + # test image's entrypoint with cmds +- isula run --name embedded_entrypoint1 test:v1 /bin ++ isula run --runtime lcr --name embedded_entrypoint1 test:v1 /bin + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - test image's entrypoint with cmds failed" && ((ret++)) + + isula rm embedded_entrypoint1 + + # test image's entrypoint override image's entrypoint +- isula run --entrypoint=/bin/ls --name embedded_entrypoint1 test:v1 /bin ++ isula run --runtime lcr --entrypoint=/bin/ls --name embedded_entrypoint1 test:v1 /bin + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - test image's entrypoint override image's entrypoint failed" && ((ret++)) + + isula rm embedded_entrypoint1 +@@ -464,7 +464,7 @@ function test_entrypoint() + isula load -i "$embedded_manifest_invalid" -t embedded + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - test entrypoint with variable failed" && ((ret++)) + +- isula run -e env_id=me --name embedded_entrypoint1 test:v1 ++ isula run --runtime lcr -e env_id=me --name embedded_entrypoint1 test:v1 + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - test run embedded image with env failed" && ((ret++)) + + isula rm embedded_entrypoint1 +@@ -519,7 +519,7 @@ function test_symbolic() + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - load embedded image failed" && ((ret++)) + + # run container based on embedded image +- isula run --name embedded_test_symbolic test:v1 ls /home/home/home ++ isula run --runtime lcr --name embedded_test_symbolic test:v1 ls /home/home/home + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - run container based on embedded image failed" && ((ret++)) + + isula rm embedded_test_symbolic +-- +2.42.0 + diff --git a/0038-save-sandbox-to-disk-after-network-ready.patch b/0038-save-sandbox-to-disk-after-network-ready.patch new file mode 100644 index 0000000..b77ff29 --- /dev/null +++ b/0038-save-sandbox-to-disk-after-network-ready.patch @@ -0,0 +1,68 @@ +From e33b7915d9ef5092252bc3ce5d93fbde74d73990 Mon Sep 17 00:00:00 2001 +From: jikai +Date: Mon, 27 Nov 2023 15:09:39 +0800 +Subject: [PATCH 38/64] save sandbox to disk after network ready + +Signed-off-by: jikai +--- + .../cri/v1/v1_cri_pod_sandbox_manager_service.cc | 13 ++++++++++--- + src/daemon/sandbox/sandbox.cc | 6 ------ + 2 files changed, 10 insertions(+), 9 deletions(-) + +diff --git a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc +index 0f6b8508..a0c45111 100644 +--- a/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc ++++ b/src/daemon/entry/cri/v1/v1_cri_pod_sandbox_manager_service.cc +@@ -358,14 +358,21 @@ auto PodSandboxManagerService::RunPodSandbox(const runtime::v1::PodSandboxConfig + goto cleanup_sandbox; + } + +- // Step 8: Call sandbox create. ++ // Step 8: Save sandbox to disk ++ sandbox->Save(error); ++ if (error.NotEmpty()) { ++ ERROR("Failed to save sandbox, %s", sandboxName.c_str()); ++ goto cleanup_network; ++ } ++ ++ // Step 9: Call sandbox create. + sandbox->Create(error); + if (error.NotEmpty()) { + ERROR("Failed to create sandbox: %s", sandboxName.c_str()); + goto cleanup_network; + } + +- // Step 9: Save network settings json to disk ++ // Step 10: Save network settings json to disk + // Update network settings before start sandbox since sandbox container will use the sandbox key + if (namespace_is_cni(networkMode.c_str())) { + Errors tmpErr; +@@ -376,7 +383,7 @@ auto PodSandboxManagerService::RunPodSandbox(const runtime::v1::PodSandboxConfig + } + } + +- // Step 10: Call sandbox start. ++ // Step 11: Call sandbox start. + sandbox->Start(error); + if (error.NotEmpty()) { + ERROR("Failed to start sandbox: %s", sandboxName.c_str()); +diff --git a/src/daemon/sandbox/sandbox.cc b/src/daemon/sandbox/sandbox.cc +index b1832265..9fe9fa48 100644 +--- a/src/daemon/sandbox/sandbox.cc ++++ b/src/daemon/sandbox/sandbox.cc +@@ -599,12 +599,6 @@ void Sandbox::PrepareSandboxDirs(Errors &error) + goto out; + } + +- if (!Save(error)) { +- error.Errorf("Failed to save sandbox, %s", m_id.c_str()); +- ERROR("Failed to save sandbox, %s", m_id.c_str()); +- goto out; +- } +- + umask(mask); + return; + +-- +2.42.0 + diff --git a/0039-fix-the-problem-of-abnormal-branches-not-waiting-for.patch b/0039-fix-the-problem-of-abnormal-branches-not-waiting-for.patch new file mode 100644 index 0000000..0f878d4 --- /dev/null +++ b/0039-fix-the-problem-of-abnormal-branches-not-waiting-for.patch @@ -0,0 +1,153 @@ +From b26654a73694c20fcd895b3b93ad5d42a1d5b3fb Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Mon, 27 Nov 2023 14:52:43 +0800 +Subject: [PATCH 39/64] fix the problem of abnormal branches not waiting for + child processes + +Signed-off-by: zhongtao +--- + src/cmd/isulad-shim/common.c | 6 +++--- + src/cmd/isulad-shim/process.c | 14 ++++++++------ + src/daemon/modules/runtime/isula/isula_rt_ops.c | 16 ++++++++++------ + src/daemon/modules/runtime/shim/shim_rt_ops.c | 15 +++++++++------ + 4 files changed, 30 insertions(+), 21 deletions(-) + +diff --git a/src/cmd/isulad-shim/common.c b/src/cmd/isulad-shim/common.c +index 48d266dc..3cc7d2a7 100644 +--- a/src/cmd/isulad-shim/common.c ++++ b/src/cmd/isulad-shim/common.c +@@ -126,12 +126,12 @@ int cmd_combined_output(const char *binary, const char *params[], void *output, + } + *output_len = isula_file_read_nointr(stdio[0], output, BUFSIZ - 1); + +- close(stdio[0]); +- close(exec_fd[0]); +- wait(&status); + ret = SHIM_OK; + + out: ++ close(stdio[0]); ++ close(exec_fd[0]); ++ wait(&status); + if (ret != SHIM_OK) { + kill(pid, 9); + } +diff --git a/src/cmd/isulad-shim/process.c b/src/cmd/isulad-shim/process.c +index 187067d2..e8cb9b32 100644 +--- a/src/cmd/isulad-shim/process.c ++++ b/src/cmd/isulad-shim/process.c +@@ -1472,7 +1472,7 @@ static void exec_runtime_process(process_t *p, int exec_fd) + const char *params[MAX_RUNTIME_ARGS] = { 0 }; + get_runtime_cmd(p, log_path, pid_path, process_desc, params); + execvp(p->runtime, (char * const *)params); +- (void)dprintf(exec_fd, "fork/exec error: %s", strerror(errno)); ++ (void)dprintf(exec_fd, "run process: %s error: %s", p->runtime, strerror(errno)); + _exit(EXIT_FAILURE); + } + +@@ -1510,11 +1510,6 @@ int create_process(process_t *p) + close_fd(&p->stdio->resize); + } + nread = isula_file_read_nointr(exec_fd[0], exec_buff, sizeof(exec_buff) - 1); +- if (nread > 0) { +- write_message(ERR_MSG, "runtime error"); +- ret = SHIM_ERR; +- goto out; +- } + + /* block to wait runtime pid exit */ + ret = waitpid(pid, NULL, 0); +@@ -1524,6 +1519,13 @@ int create_process(process_t *p) + goto out; + } + ++ // if an error occurs in exec_runtime_process, jump directly to the out branch after waitpid. ++ if (nread > 0) { ++ write_message(ERR_MSG, "%s", exec_buff); ++ ret = SHIM_ERR; ++ goto out; ++ } ++ + /* save runtime pid */ + data = read_text_file("pid"); + if (data == NULL) { +diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c +index 859356e5..5d7ae500 100644 +--- a/src/daemon/modules/runtime/isula/isula_rt_ops.c ++++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c +@@ -906,17 +906,13 @@ realexec: + } + + execvp(SHIM_BINARY, (char * const *)params); +- (void)dprintf(shim_stderr_pipe[1], "exec failed: %s", strerror(errno)); ++ (void)dprintf(shim_stderr_pipe[1], "run process: %s failed: %s", SHIM_BINARY, strerror(errno)); ++ exit(EXIT_FAILURE); + } + + close(shim_stderr_pipe[1]); + close(shim_stdout_pipe[1]); + num = util_read_nointr(shim_stderr_pipe[0], exec_buff, sizeof(exec_buff) - 1); +- if (num > 0) { +- ERROR("Exec failed: %s", exec_buff); +- ret = -1; +- goto out; +- } + + status = util_wait_for_pid_status(pid); + if (status < 0) { +@@ -925,6 +921,14 @@ realexec: + goto out; + } + ++ // if failed to exec, jump directly to the out branch after waitpid. ++ if (num > 0) { ++ ERROR("%s", exec_buff); ++ isulad_set_error_message("%s", exec_buff); ++ ret = -1; ++ goto out; ++ } ++ + *shim_exit_code = status_to_exit_code(status); + if (*shim_exit_code != 0) { + ERROR("Isulad-shim exit error"); +diff --git a/src/daemon/modules/runtime/shim/shim_rt_ops.c b/src/daemon/modules/runtime/shim/shim_rt_ops.c +index 5066f804..81daf224 100644 +--- a/src/daemon/modules/runtime/shim/shim_rt_ops.c ++++ b/src/daemon/modules/runtime/shim/shim_rt_ops.c +@@ -251,17 +251,13 @@ static int shim_bin_v2_create(const char *runtime, const char *id, const char *w + } + + execvp(binary, (char * const *)params); +- (void)dprintf(exec_fd[1], "exec failed: %s", strerror(errno)); ++ (void)dprintf(exec_fd[1], "run process: %s failed: %s", binary, strerror(errno)); + exit(EXIT_FAILURE); + } + + close(exec_fd[1]); + exec_fd[1] = -1; +- if (util_read_nointr(exec_fd[0], exec_buff, sizeof(exec_buff) - 1) > 0) { +- ERROR("exec failed: %s", exec_buff); +- ret = -1; +- goto out; +- } ++ nret = util_read_nointr(exec_fd[0], exec_buff, sizeof(exec_buff) - 1); + close(exec_fd[0]); + exec_fd[0] = -1; + +@@ -272,6 +268,13 @@ static int shim_bin_v2_create(const char *runtime, const char *id, const char *w + goto out; + } + ++ // if failed to exec, jump directly to the out branch after waitpid. ++ if (nret > 0) { ++ ERROR("%s", exec_buff); ++ ret = -1; ++ goto out; ++ } ++ + status = status_to_exit_code(status); + + close(out_fd[1]); +-- +2.42.0 + diff --git a/0040-remove-embedded-image-support-in-readme.patch b/0040-remove-embedded-image-support-in-readme.patch new file mode 100644 index 0000000..9ace537 --- /dev/null +++ b/0040-remove-embedded-image-support-in-readme.patch @@ -0,0 +1,62 @@ +From 6f9661d7e12e22ff4eeb76647cbe862c5fe7e18d Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Mon, 27 Nov 2023 20:50:33 +0800 +Subject: [PATCH 40/64] remove embedded image support in readme + +Signed-off-by: zhongtao +--- + README.md | 6 +----- + README_zh.md | 6 +----- + 2 files changed, 2 insertions(+), 10 deletions(-) + +diff --git a/README.md b/README.md +index e7949dee..970b6e72 100644 +--- a/README.md ++++ b/README.md +@@ -32,7 +32,7 @@ kata-runtime start secure containers with lightweight virtual machines. + + ### Image + +-`iSulad` supports multiple image formats, including OCI, external rootfs and embedded image. ++`iSulad` supports multiple image formats, including OCI and external rootfs. + + #### OCI + +@@ -42,10 +42,6 @@ OCI is a docker-compatible image format that supports pulling images and running + + External rootfs allows users to prepare a bootable `root fs` directory, which is mainly used in system container scenarios. + +-#### embedded image +- +-Embedded image is a unique embedded image format of `iSulad`, which occupies low resources and is mainly used in embedded application scenarios. +- + ### Operation Interface + + `iSulad` provides two different interfaces for image and container management operations: CLI and CRI. +diff --git a/README_zh.md b/README_zh.md +index 1c4dff4f..5db28f3a 100755 +--- a/README_zh.md ++++ b/README_zh.md +@@ -32,7 +32,7 @@ kata-runtime是一个安全容器runtime,用于启动安全容器时使用。 + + ### Image + +-`iSulad`支持多种镜像格式,包括OCI标准镜像格式、external rootfs镜像格式和embedded image镜像格式。 ++`iSulad`支持多种镜像格式,包括OCI标准镜像格式和external rootfs镜像格式。 + + #### OCI + +@@ -42,10 +42,6 @@ OCI标准镜像格式是与docker兼容的镜像格式,支持从远程镜像 + + external rootfs镜像格式允许用户自行准备可启动的`root fs`目录,主要用于系统容器场景。 + +-#### embedded image +- +-embedded image镜像格式是`iSulad`特有的嵌入式镜像格式,占用资源低,主要用于嵌入式应用场景。 +- + ### Operation Interface + + `iSulad`提供两种不同的镜像和容器管理操作接口,分别为CLI和CRI。 +-- +2.42.0 + diff --git a/0041-Acquire-system-info-in-on-demand.patch b/0041-Acquire-system-info-in-on-demand.patch new file mode 100644 index 0000000..4e178e8 --- /dev/null +++ b/0041-Acquire-system-info-in-on-demand.patch @@ -0,0 +1,392 @@ +From 13bc364cb5d8c03b701dde2b2811be84ee608e92 Mon Sep 17 00:00:00 2001 +From: xuxuepeng +Date: Fri, 24 Nov 2023 14:18:32 +0800 +Subject: [PATCH 41/64] Acquire system info in on demand + +Signed-off-by: xuxuepeng +--- + src/cmd/isulad/main.c | 2 -- + src/daemon/common/sysinfo.c | 10 +----- + src/daemon/common/sysinfo.h | 6 ++++ + .../executor/container_cb/execution_create.c | 32 +++++++++---------- + .../executor/container_cb/execution_extend.c | 9 +++++- + src/daemon/modules/spec/verify.c | 32 ++++++++----------- + src/daemon/modules/spec/verify.h | 5 +-- + test/mocks/sysinfo_mock.cc | 8 +++++ + test/mocks/sysinfo_mock.h | 1 + + test/mocks/verify_mock.cc | 4 +-- + test/mocks/verify_mock.h | 2 +- + 11 files changed, 60 insertions(+), 51 deletions(-) + +diff --git a/src/cmd/isulad/main.c b/src/cmd/isulad/main.c +index 5b971a72..95454e2a 100644 +--- a/src/cmd/isulad/main.c ++++ b/src/cmd/isulad/main.c +@@ -1765,8 +1765,6 @@ int main(int argc, char **argv) + + update_isulad_rlimits(); + +- (void)get_sys_info(true); +- + clock_gettime(CLOCK_MONOTONIC, &t_start); + + if (pre_init_daemon(argc, argv) != 0) { +diff --git a/src/daemon/common/sysinfo.c b/src/daemon/common/sysinfo.c +index 39338925..28665834 100644 +--- a/src/daemon/common/sysinfo.c ++++ b/src/daemon/common/sysinfo.c +@@ -19,7 +19,6 @@ + #include + #include + +-#include + #include + + #include "err_msg.h" +@@ -30,8 +29,6 @@ + #define etcOsRelease "/etc/os-release" + #define altOsRelease "/usr/lib/os-release" + +-static sysinfo_t *g_sysinfo = NULL; +- + static char *get_pagesize(const char *pline) + { + size_t headlen; +@@ -382,10 +379,6 @@ sysinfo_t *get_sys_info(bool quiet) + sysinfo_t *sysinfo = NULL; + int ret = 0; + +- if (g_sysinfo != NULL) { +- return g_sysinfo; +- } +- + sysinfo = util_common_calloc_s(sizeof(sysinfo_t)); + if (sysinfo == NULL) { + ERROR("Out of memory"); +@@ -413,7 +406,6 @@ sysinfo_t *get_sys_info(bool quiet) + if (ret != 0) { + goto out; + } +- g_sysinfo = sysinfo; + out: + if (ret != 0) { + free_sysinfo(sysinfo); +@@ -577,7 +569,7 @@ char *sysinfo_cgroup_controller_cpurt_mnt_path(void) + __isula_auto_free char *mnt = NULL; + __isula_auto_free char *root = NULL; + char fpath[PATH_MAX] = { 0 }; +- sysinfo_t *sysinfo = NULL; ++ __isula_auto_sysinfo_t sysinfo_t *sysinfo = NULL; + + sysinfo = get_sys_info(true); + if (sysinfo == NULL) { +diff --git a/src/daemon/common/sysinfo.h b/src/daemon/common/sysinfo.h +index 363576a9..cb44d1c5 100644 +--- a/src/daemon/common/sysinfo.h ++++ b/src/daemon/common/sysinfo.h +@@ -21,6 +21,7 @@ extern "C" { + + #include + #include ++#include + + #include "cgroup.h" + +@@ -96,6 +97,11 @@ void free_mounts_info(mountinfo_t **minfos); + + char *sysinfo_cgroup_controller_cpurt_mnt_path(void); + ++// define auto free function callback for sysinfo_t ++define_auto_cleanup_callback(free_sysinfo, sysinfo_t) ++// define auto free macro for sysinfo_t ++#define __isula_auto_sysinfo_t auto_cleanup_tag(free_sysinfo) ++ + #ifdef __cplusplus + } + #endif +diff --git a/src/daemon/executor/container_cb/execution_create.c b/src/daemon/executor/container_cb/execution_create.c +index 6b6c3b75..ca2a9163 100644 +--- a/src/daemon/executor/container_cb/execution_create.c ++++ b/src/daemon/executor/container_cb/execution_create.c +@@ -145,7 +145,7 @@ static int merge_external_rootfs_to_host_config(host_config *host_spec, const ch + return 0; + } + +-static host_config *get_host_spec(const container_create_request *request) ++static host_config *get_host_spec(const container_create_request *request, const sysinfo_t *sysinfo) + { + host_config *host_spec = NULL; + +@@ -158,7 +158,7 @@ static host_config *get_host_spec(const container_create_request *request) + goto error_out; + } + +- if (verify_host_config_settings(host_spec, false)) { ++ if (verify_host_config_settings(host_spec, sysinfo, false)) { + ERROR("Failed to verify host config settings"); + goto error_out; + } +@@ -1109,17 +1109,9 @@ static int preparate_runtime_environment(const container_create_request *request + return 0; + } + +-static int adapt_host_spec(host_config *host_spec) ++static int adapt_host_spec(host_config *host_spec, const sysinfo_t *sysinfo) + { + int ret = 0; +- sysinfo_t *sysinfo = NULL; +- +- sysinfo = get_sys_info(true); +- if (sysinfo == NULL) { +- ERROR("Can not get system info"); +- ret = -1; +- goto out; +- } + + if (host_spec->memory > 0 && host_spec->memory_swap == 0 && sysinfo->cgmeminfo.swap) { + if (host_spec->memory > (INT64_MAX / 2)) { +@@ -1136,14 +1128,14 @@ out: + } + + static int get_basic_spec(const container_create_request *request, host_config **host_spec, +- container_config **container_spec) ++ container_config **container_spec, const sysinfo_t *sysinfo) + { +- *host_spec = get_host_spec(request); ++ *host_spec = get_host_spec(request, sysinfo); + if (*host_spec == NULL) { + return -1; + } + +- if (adapt_host_spec(*host_spec) != 0) { ++ if (adapt_host_spec(*host_spec, sysinfo) != 0) { + return -1; + } + +@@ -1393,6 +1385,7 @@ int container_create_cb(const container_create_request *request, container_creat + int ret = 0; + bool skip_id_name_manage = false; + bool skip_sandbox_key_manage = false; ++ __isula_auto_sysinfo_t sysinfo_t *sysinfo = NULL; + + DAEMON_CLEAR_ERRMSG(); + +@@ -1413,7 +1406,14 @@ int container_create_cb(const container_create_request *request, container_creat + goto clean_nameindex; + } + +- if (get_basic_spec(request, &host_spec, &container_spec) != 0) { ++ sysinfo = get_sys_info(true); ++ if (sysinfo == NULL) { ++ ERROR("Failed to get system info"); ++ cc = ISULAD_ERR_EXEC; ++ goto clean_nameindex; ++ } ++ ++ if (get_basic_spec(request, &host_spec, &container_spec, sysinfo) != 0) { + cc = ISULAD_ERR_INPUT; + goto clean_container_root_dir; + } +@@ -1540,7 +1540,7 @@ int container_create_cb(const container_create_request *request, container_creat + goto clean_netns; + } + +- if (verify_container_settings(oci_spec) != 0) { ++ if (verify_container_settings(oci_spec, sysinfo) != 0) { + ERROR("Failed to verify container settings"); + cc = ISULAD_ERR_EXEC; + goto umount_channel; +diff --git a/src/daemon/executor/container_cb/execution_extend.c b/src/daemon/executor/container_cb/execution_extend.c +index de017b4e..25ec5d3b 100644 +--- a/src/daemon/executor/container_cb/execution_extend.c ++++ b/src/daemon/executor/container_cb/execution_extend.c +@@ -1110,8 +1110,15 @@ static int update_host_config_check(container_t *cont, host_config *hostconfig) + { + int ret = 0; + const char *id = cont->common_config->id; ++ __isula_auto_sysinfo_t sysinfo_t *sysinfo = NULL; + +- ret = verify_host_config_settings(hostconfig, true); ++ sysinfo = get_sys_info(true); ++ if (sysinfo == NULL) { ++ ERROR("Failed to get system info for updating container %s", id); ++ return -1; ++ } ++ ++ ret = verify_host_config_settings(hostconfig, sysinfo, true); + if (ret != 0) { + return -1; + } +diff --git a/src/daemon/modules/spec/verify.c b/src/daemon/modules/spec/verify.c +index 2a8b3259..b9e3c606 100644 +--- a/src/daemon/modules/spec/verify.c ++++ b/src/daemon/modules/spec/verify.c +@@ -41,7 +41,6 @@ + #include "constants.h" + #include "err_msg.h" + #include "isula_libutils/log.h" +-#include "sysinfo.h" + #include "selinux_label.h" + #include "image_api.h" + #include "utils.h" +@@ -1614,16 +1613,13 @@ out: + } + + /* verify container settings */ +-int verify_container_settings(const oci_runtime_spec *container) ++int verify_container_settings(const oci_runtime_spec *container, const sysinfo_t *sysinfo) + { + int ret = 0; +- sysinfo_t *sysinfo = NULL; + +- sysinfo = get_sys_info(true); +- if (sysinfo == NULL) { +- ERROR("Can not get system info"); +- ret = -1; +- goto out; ++ if (container == NULL || sysinfo == NULL) { ++ ERROR("Invalid input arguments for verifying container settings"); ++ return -1; + } + + if (!util_valid_host_name(container->hostname)) { +@@ -1987,16 +1983,9 @@ static int host_config_settings_restart_policy(const host_config *hostconfig) + return verify_restart_policy_name(rp, hostconfig); + } + +-static int host_config_settings_with_sysinfo(host_config *hostconfig, bool update) ++static int host_config_settings_with_sysinfo(host_config *hostconfig, const sysinfo_t *sysinfo, bool update) + { + int ret = 0; +- sysinfo_t *sysinfo = NULL; +- +- sysinfo = get_sys_info(true); +- if (sysinfo == NULL) { +- ERROR("Can not get system info"); +- return -1; +- } + + ret = verify_host_config_hugetlbs(sysinfo, &(hostconfig->hugetlbs), &(hostconfig->hugetlbs_len)); + if (ret != 0) { +@@ -2055,7 +2044,7 @@ out: + } + + /* verify host config settings */ +-int verify_host_config_settings(host_config *hostconfig, bool update) ++int verify_host_config_settings(host_config *hostconfig, const sysinfo_t *sysinfo, bool update) + { + int ret = 0; + #ifdef ENABLE_USERNS_REMAP +@@ -2066,6 +2055,13 @@ int verify_host_config_settings(host_config *hostconfig, bool update) + goto out; + } + ++ if (sysinfo == NULL) { ++ ERROR("Invalid sysinfo for verifying host config settings"); ++ isulad_set_error_message("Invalid sysinfo for verifying host config settings"); ++ ret = -1; ++ goto out; ++ } ++ + #ifdef ENABLE_USERNS_REMAP + if (userns_remap != NULL && hostconfig->user_remap != NULL) { + ERROR("invalid --user-remap command option, daemon already configed --userns-remap"); +@@ -2081,7 +2077,7 @@ int verify_host_config_settings(host_config *hostconfig, bool update) + goto out; + } + +- ret = host_config_settings_with_sysinfo(hostconfig, update); ++ ret = host_config_settings_with_sysinfo(hostconfig, sysinfo, update); + if (ret != 0) { + goto out; + } +diff --git a/src/daemon/modules/spec/verify.h b/src/daemon/modules/spec/verify.h +index 21e8fba8..0224f9fb 100644 +--- a/src/daemon/modules/spec/verify.h ++++ b/src/daemon/modules/spec/verify.h +@@ -20,18 +20,19 @@ + #include "isula_libutils/oci_runtime_spec.h" + #include "isula_libutils/host_config.h" + #include "isula_libutils/container_config.h" ++#include "sysinfo.h" + + #ifdef __cplusplus + extern "C" { + #endif + +-int verify_container_settings(const oci_runtime_spec *container); ++int verify_container_settings(const oci_runtime_spec *container, const sysinfo_t *sysinfo); + + int verify_oci_hook(const oci_runtime_spec_hooks *h); + + int verify_container_settings_start(const oci_runtime_spec *oci_spec); + +-int verify_host_config_settings(host_config *hostconfig, bool update); ++int verify_host_config_settings(host_config *hostconfig, const sysinfo_t *sysinfo, bool update); + + int verify_container_config(const container_config *container_spec, const char *runtime); + +diff --git a/test/mocks/sysinfo_mock.cc b/test/mocks/sysinfo_mock.cc +index f9abc786..d8f33f84 100644 +--- a/test/mocks/sysinfo_mock.cc ++++ b/test/mocks/sysinfo_mock.cc +@@ -63,6 +63,14 @@ char *validate_hugetlb(const char *pagesize, uint64_t limit) + return nullptr; + } + ++sysinfo_t *get_sys_info(bool quiet) ++{ ++ if (g_sysinfo_mock != nullptr) { ++ return g_sysinfo_mock->GetSysInfo(quiet); ++ } ++ return nullptr; ++} ++ + void free_sysinfo(sysinfo_t *sysinfo) + { + if (g_sysinfo_mock != nullptr) { +diff --git a/test/mocks/sysinfo_mock.h b/test/mocks/sysinfo_mock.h +index 45208b0f..2b8e926d 100644 +--- a/test/mocks/sysinfo_mock.h ++++ b/test/mocks/sysinfo_mock.h +@@ -26,6 +26,7 @@ public: + MOCK_METHOD1(FreeMountsInfo, void(mountinfo_t **minfos)); + MOCK_METHOD0(GetDefaultHugePageSize, char *(void)); + MOCK_METHOD2(ValidateHugetlb, char*(const char *pagesize, uint64_t limit)); ++ MOCK_METHOD1(GetSysInfo, sysinfo_t *(bool quiet)); + MOCK_METHOD1(FreeSysinfo, void(sysinfo_t *sysinfo)); + }; + +diff --git a/test/mocks/verify_mock.cc b/test/mocks/verify_mock.cc +index 0e7e7461..4c481676 100644 +--- a/test/mocks/verify_mock.cc ++++ b/test/mocks/verify_mock.cc +@@ -24,10 +24,10 @@ void MockVerify_SetMock(MockVerify *mock) + g_verify_mock = mock; + } + +-int verify_host_config_settings(host_config *hostconfig, bool update) ++int verify_host_config_settings(host_config *hostconfig, const sysinfo_t *sysinfo, bool update) + { + if (g_verify_mock != nullptr) { +- return g_verify_mock->VerifyHostConfigSettings(hostconfig, update); ++ return g_verify_mock->VerifyHostConfigSettings(hostconfig, sysinfo, update); + } + return 0; + } +diff --git a/test/mocks/verify_mock.h b/test/mocks/verify_mock.h +index 7890159f..b9ad8627 100644 +--- a/test/mocks/verify_mock.h ++++ b/test/mocks/verify_mock.h +@@ -21,7 +21,7 @@ + + class MockVerify { + public: +- MOCK_METHOD2(VerifyHostConfigSettings, int(host_config *hostconfig, bool update)); ++ MOCK_METHOD3(VerifyHostConfigSettings, int(host_config *hostconfig, const sysinfo_t *sysinfo, bool update)); + }; + + void MockVerify_SetMock(MockVerify* mock); +-- +2.42.0 + diff --git a/0042-2268-bugfix-for-the-bliko-zero-value-exception-when-.patch b/0042-2268-bugfix-for-the-bliko-zero-value-exception-when-.patch new file mode 100644 index 0000000..2c9f725 --- /dev/null +++ b/0042-2268-bugfix-for-the-bliko-zero-value-exception-when-.patch @@ -0,0 +1,92 @@ +From dddba4ec73b56bc2fcf3a95171fad104e962dfda Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Wed, 29 Nov 2023 09:33:53 +0000 +Subject: [PATCH 42/64] =?UTF-8?q?!2268=20bugfix=20for=20the=20bliko=20zero?= + =?UTF-8?q?=20value=20exception=20when=20executing=20the=20stats=20command?= + =?UTF-8?q?=20on=20the=20oci=20container=20*=20bugfix=20for=20the=20bliko?= + =?UTF-8?q?=20zero=20value=20exception=20when=20executing=20the=20stats=20?= + =?UTF-8?q?com=E2=80=A6?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + .../modules/runtime/isula/isula_rt_ops.c | 55 +++++++++++++------ + 1 file changed, 38 insertions(+), 17 deletions(-) + +diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c +index 5d7ae500..1e2ecdb2 100644 +--- a/src/daemon/modules/runtime/isula/isula_rt_ops.c ++++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c +@@ -610,6 +610,43 @@ out: + return ret; + } + ++static void transform_stats_info_from_runtime(shim_client_runtime_stats *stats, struct runtime_container_resources_stats_info *info) ++{ ++ if (stats == NULL || stats->data == NULL) { ++ return; ++ } ++ if (stats->data->pids != NULL) { ++ info->pids_current = stats->data->pids->current; ++ } ++ if (stats->data->cpu != NULL && stats->data->cpu->usage != NULL) { ++ info->cpu_use_nanos = stats->data->cpu->usage->total; ++ info->cpu_system_use = stats->data->cpu->usage->kernel; ++ } ++ shim_client_runtime_stats_data_memory *memory = stats->data->memory; ++ if (memory != NULL && memory->usage != NULL) { ++ info->mem_used = memory->usage->usage; ++ info->mem_limit = memory->usage->limit; ++ } ++ if (memory != NULL && memory->raw != NULL) { ++ info->inactive_file_total = memory->raw->total_inactive_file; ++ info->rss_bytes = memory->raw->rss; ++ info->page_faults = memory->raw->pgfault; ++ info->major_page_faults = memory->raw->pgmajfault; ++ } ++ shim_client_runtime_stats_data_blkio *blkio = stats->data->blkio; ++ if (blkio == NULL) { ++ return; ++ } ++ for (size_t i = 0; i < blkio->io_service_bytes_recursive_len; i++) { ++ if (strcasecmp(blkio->io_service_bytes_recursive[i]->op, "read") == 0) { ++ info->blkio_read += blkio->io_service_bytes_recursive[i]->value; ++ } ++ if (strcasecmp(blkio->io_service_bytes_recursive[i]->op, "write") == 0) { ++ info->blkio_write += blkio->io_service_bytes_recursive[i]->value; ++ } ++ } ++} ++ + static int runtime_call_stats(const char *workdir, const char *runtime, const char *id, + struct runtime_container_resources_stats_info *info) + { +@@ -658,23 +695,7 @@ static int runtime_call_stats(const char *workdir, const char *runtime, const ch + goto out; + } + +- if (stats != NULL && stats->data != NULL && stats->data->pids != NULL) { +- info->pids_current = stats->data->pids->current; +- } +- if (stats != NULL && stats->data != NULL && stats->data->cpu != NULL && stats->data->cpu->usage) { +- info->cpu_use_nanos = stats->data->cpu->usage->total; +- info->cpu_system_use = stats->data->cpu->usage->kernel; +- } +- if (stats != NULL && stats->data != NULL && stats->data->memory != NULL && stats->data->memory->usage) { +- info->mem_used = stats->data->memory->usage->usage; +- info->mem_limit = stats->data->memory->usage->limit; +- } +- if (stats != NULL && stats->data != NULL && stats->data->memory != NULL && stats->data->memory->raw) { +- info->inactive_file_total = stats->data->memory->raw->total_inactive_file; +- info->rss_bytes = stats->data->memory->raw->rss; +- info->page_faults = stats->data->memory->raw->pgfault; +- info->major_page_faults = stats->data->memory->raw->pgmajfault; +- } ++ transform_stats_info_from_runtime(stats, info); + + out: + free_shim_client_runtime_stats(stats); +-- +2.42.0 + diff --git a/0043-move-variable-declaration-out-of-loop.patch b/0043-move-variable-declaration-out-of-loop.patch new file mode 100644 index 0000000..26748eb --- /dev/null +++ b/0043-move-variable-declaration-out-of-loop.patch @@ -0,0 +1,34 @@ +From 261a924b656eea9eff2ca6cbdd611eb1f9555af7 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Thu, 30 Nov 2023 16:02:44 +1400 +Subject: [PATCH 43/64] move variable declaration out of loop + +Signed-off-by: zhongtao +--- + src/daemon/modules/runtime/isula/isula_rt_ops.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c +index 1e2ecdb2..3950ff4a 100644 +--- a/src/daemon/modules/runtime/isula/isula_rt_ops.c ++++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c +@@ -612,6 +612,7 @@ out: + + static void transform_stats_info_from_runtime(shim_client_runtime_stats *stats, struct runtime_container_resources_stats_info *info) + { ++ size_t i; + if (stats == NULL || stats->data == NULL) { + return; + } +@@ -637,7 +638,7 @@ static void transform_stats_info_from_runtime(shim_client_runtime_stats *stats, + if (blkio == NULL) { + return; + } +- for (size_t i = 0; i < blkio->io_service_bytes_recursive_len; i++) { ++ for (i = 0; i < blkio->io_service_bytes_recursive_len; i++) { + if (strcasecmp(blkio->io_service_bytes_recursive[i]->op, "read") == 0) { + info->blkio_read += blkio->io_service_bytes_recursive[i]->value; + } +-- +2.42.0 + diff --git a/0044-2289-check-protobuf-and-grpc-version-in-cmake-for-cr.patch b/0044-2289-check-protobuf-and-grpc-version-in-cmake-for-cr.patch new file mode 100644 index 0000000..5fa3a05 --- /dev/null +++ b/0044-2289-check-protobuf-and-grpc-version-in-cmake-for-cr.patch @@ -0,0 +1,40 @@ +From 8045fcfb3765698d8cc3f07186fcc29d6702ee71 Mon Sep 17 00:00:00 2001 +From: jake +Date: Thu, 30 Nov 2023 11:58:47 +0000 +Subject: [PATCH 44/64] !2289 check protobuf and grpc version in cmake for cri + v1 * check protobuf and grpc version in cmake for cri v1 + +--- + cmake/checker.cmake | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/cmake/checker.cmake b/cmake/checker.cmake +index cc4a1fc3..e19618e4 100644 +--- a/cmake/checker.cmake ++++ b/cmake/checker.cmake +@@ -125,7 +125,11 @@ endif() + + if (GRPC_CONNECTOR) + # check protobuf +- pkg_check_modules(PC_PROTOBUF "protobuf>=3.1.0") ++ if (ENABLE_CRI_API_V1) ++ pkg_check_modules(PC_PROTOBUF "protobuf>=3.14.0") ++ else() ++ pkg_check_modules(PC_PROTOBUF "protobuf>=3.1.0") ++ endif() + find_library(PROTOBUF_LIBRARY protobuf + HINTS ${PC_PROTOBUF_LIBDIR} ${PC_PROTOBUF_LIBRARY_DIRS}) + _CHECK(PROTOBUF_LIBRARY "PROTOBUF_LIBRARY-NOTFOUND" "libprotobuf.so") +@@ -136,6 +140,9 @@ if (GRPC_CONNECTOR) + _CHECK(CMD_GRPC_CPP_PLUGIN "CMD_GRPC_CPP_PLUGIN-NOTFOUND" "grpc_cpp_plugin") + + # check grpc ++ if (ENABLE_CRI_API_V1) ++ pkg_check_modules(PC_GRPC++ "grpc++>=1.41.0") ++ endif() + find_path(GRPC_INCLUDE_DIR grpc/grpc.h) + _CHECK(GRPC_INCLUDE_DIR "GRPC_INCLUDE_DIR-NOTFOUND" "grpc/grpc.h") + find_library(GRPC_PP_REFLECTION_LIBRARY grpc++_reflection) +-- +2.42.0 + diff --git a/0045-improve-ut-for-devicemapper.patch b/0045-improve-ut-for-devicemapper.patch new file mode 100644 index 0000000..ad87cba --- /dev/null +++ b/0045-improve-ut-for-devicemapper.patch @@ -0,0 +1,381 @@ +From 2ad7ecf5adbd75f1ba4678e69d768d4b807ae08d Mon Sep 17 00:00:00 2001 +From: jikai +Date: Wed, 29 Nov 2023 17:08:31 +0800 +Subject: [PATCH 45/64] improve ut for devicemapper + +Signed-off-by: jikai +--- + .../storage/layers/devmapper/CMakeLists.txt | 8 +- + .../id | 1 + + .../layers/devmapper/driver_devmapper_ut.cc | 209 +++++++++++++----- + 3 files changed, 165 insertions(+), 53 deletions(-) + create mode 100644 test/image/oci/storage/layers/devmapper/data/devicemapper/mnt/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d/id + +diff --git a/test/image/oci/storage/layers/devmapper/CMakeLists.txt b/test/image/oci/storage/layers/devmapper/CMakeLists.txt +index f98de1a8..e6ba0307 100644 +--- a/test/image/oci/storage/layers/devmapper/CMakeLists.txt ++++ b/test/image/oci/storage/layers/devmapper/CMakeLists.txt +@@ -23,14 +23,18 @@ add_executable(${DRIVER_DEVMAPPER_EXE} + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/tar/util_gzip.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/utils/sha256/sha256.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/common/err_msg.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/common/selinux_label.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/driver.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/deviceset.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/driver_devmapper.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/metadata_store.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/devmapper/wrapper_devmapper.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2/driver_overlay2.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/remote_layer_support/ro_symlink_maintain.c ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../src/daemon/modules/image/oci/storage/layer_store/graphdriver/quota/project_quota.c + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../mocks/libdevmapper_mock.cc ++ ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../mocks/isulad_config_mock.cc + driver_devmapper_ut.cc) + + target_include_directories(${DRIVER_DEVMAPPER_EXE} PUBLIC +@@ -56,7 +60,7 @@ target_include_directories(${DRIVER_DEVMAPPER_EXE} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../mocks + ) + +-set_target_properties(${DRIVER_DEVMAPPER_EXE} PROPERTIES LINK_FLAGS "-Wl,--wrap,util_exec_cmd -Wl,--wrap,util_mount -Wl,--wrap,umount2") ++set_target_properties(${DRIVER_DEVMAPPER_EXE} PROPERTIES LINK_FLAGS "-Wl,--wrap,util_exec_cmd -Wl,--wrap,util_mount -Wl,--wrap,umount2 -Wl,--wrap,archive_unpack") + + target_link_libraries(${DRIVER_DEVMAPPER_EXE} + ${GTEST_BOTH_LIBRARIES} +diff --git a/test/image/oci/storage/layers/devmapper/data/devicemapper/mnt/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d/id b/test/image/oci/storage/layers/devmapper/data/devicemapper/mnt/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d/id +new file mode 100644 +index 00000000..5e6b1b2a +--- /dev/null ++++ b/test/image/oci/storage/layers/devmapper/data/devicemapper/mnt/068615102be4457b22d40c9702e4bd316dd50ae85467b0378a419b23b60ba73d/id +@@ -0,0 +1 @@ ++3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f +\ No newline at end of file +diff --git a/test/image/oci/storage/layers/devmapper/driver_devmapper_ut.cc b/test/image/oci/storage/layers/devmapper/driver_devmapper_ut.cc +index 59e53f97..088aa4d4 100644 +--- a/test/image/oci/storage/layers/devmapper/driver_devmapper_ut.cc ++++ b/test/image/oci/storage/layers/devmapper/driver_devmapper_ut.cc +@@ -16,11 +16,16 @@ + #include + #include + ++#include "driver.h" + #include "driver_devmapper.h" ++#include "driver_overlay2.h" + #include "mock.h" + #include "path.h" + #include "utils.h" ++#include "util_archive.h" + #include "libdevmapper_mock.h" ++#include "isulad_config_mock.h" ++#include "wrapper_devmapper.h" + + using ::testing::Invoke; + using ::testing::NiceMock; +@@ -29,13 +34,20 @@ using ::testing::_; + + extern "C" { + DECLARE_WRAPPER_V(util_exec_cmd, bool, (exec_func_t cb_func, void *args, const char *stdin_msg, char **stdout_msg, char **stderr_msg)); +- DEFINE_WRAPPER_V(util_exec_cmd, bool, (exec_func_t cb_func, void *args, const char *stdin_msg, char **stdout_msg, char **stderr_msg), (cb_func, args, stdin_msg, stdout_msg, stderr_msg)); ++ DEFINE_WRAPPER_V(util_exec_cmd, bool, (exec_func_t cb_func, void *args, const char *stdin_msg, char **stdout_msg, char **stderr_msg), ++ (cb_func, args, stdin_msg, stdout_msg, stderr_msg)); + + DECLARE_WRAPPER(util_mount, int, (const char *src, const char *dst, const char *mtype, const char *mntopts)); + DEFINE_WRAPPER(util_mount, int, (const char *src, const char *dst, const char *mtype, const char *mntopts), (src, dst, mtype, mntopts)); + + DECLARE_WRAPPER(umount2, int, (const char *__special_file, int __flags)); + DEFINE_WRAPPER(umount2, int, (const char *__special_file, int __flags), (__special_file, __flags)); ++ ++ DECLARE_WRAPPER(archive_unpack, int, (const io_read_wrapper *content, const char *dstdir, const archive_options *options, ++ const char *root_dir, char **errmsg)); ++ DEFINE_WRAPPER(archive_unpack, int, (const io_read_wrapper *content, const char *dstdir, const archive_options *options, ++ const char *root_dir, char **errmsg), ++ (content, dstdir, options, root_dir, errmsg)); + } + + static std::string GetDirectory() +@@ -118,6 +130,7 @@ protected: + void SetUp() override + { + MockLibdevmapper_SetMock(&m_libdevmapper_mock); ++ MockIsuladConf_SetMock(&m_isulad_conf_mock); + std::string isulad_dir { "/tmp/isulad/" }; + mkdir(isulad_dir.c_str(), 0755); + std::string root_dir = isulad_dir + "data"; +@@ -129,13 +142,18 @@ protected: + std::string cp_command = "cp -r " + std::string(data_path) + " " + isulad_dir; + ASSERT_EQ(system(cp_command.c_str()), 0); + +- char **driver_opts = static_cast(util_common_calloc_s(3 * sizeof(char *))); +- driver_opts[0] = strdup("dm.thinpooldev=/dev/mapper/isulad0-thinpool"); +- driver_opts[1] = strdup("dm.fs=ext4"); +- driver_opts[2] = strdup("dm.min_free_space=10%"); +- int driver_opts_len = 3; +- +- ASSERT_EQ(devmapper_init(&driver, nullptr, (const char **)driver_opts, driver_opts_len), -1); ++ opts = (struct storage_module_init_options *)util_common_calloc_s(sizeof(struct storage_module_init_options)); ++ opts->storage_root = strdup(root_dir.c_str()); ++ opts->storage_run_root = strdup(run_dir.c_str()); ++ opts->driver_name = strdup("devicemapper"); ++ opts->driver_opts = (char **)util_common_calloc_s(6 * sizeof(char *)); ++ opts->driver_opts[0] = strdup("dm.thinpooldev=/dev/mapper/isulad0-thinpool"); ++ opts->driver_opts[1] = strdup("dm.fs=ext4"); ++ opts->driver_opts[2] = strdup("dm.min_free_space=10%"); ++ opts->driver_opts[3] = strdup("dm.basesize=12G"); ++ opts->driver_opts[4] = strdup("dm.mkfsarg=-q"); ++ opts->driver_opts[5] = strdup("dm.mountopt=rw"); ++ opts->driver_opts_len = 6; + + EXPECT_CALL(m_libdevmapper_mock, DMTaskCreate(_)).WillRepeatedly(Invoke(invokeDMTaskCreate)); + EXPECT_CALL(m_libdevmapper_mock, DMTaskSetMessage(_, _)).WillRepeatedly(Return(1)); +@@ -152,7 +170,6 @@ protected: + EXPECT_CALL(m_libdevmapper_mock, DMUdevComplete(_)).WillRepeatedly(Return(1)); + EXPECT_CALL(m_libdevmapper_mock, DMTaskDeferredRemove(_)).WillRepeatedly(Return(1)); + +- + char *names = static_cast(util_common_calloc_s(sizeof(struct dm_names) + strlen("isulad0-pool") + 1)); + struct dm_names *dname = (struct dm_names *)names; + dname->dev = 1; +@@ -164,32 +181,76 @@ protected: + EXPECT_CALL(m_libdevmapper_mock, DMUdevGetSyncSupport()).WillOnce(Return(1)); + + MOCK_SET_V(util_exec_cmd, invokeUtilExecCmd); +- +- ASSERT_EQ(devmapper_init(&driver, driver_home.c_str(), (const char **)driver_opts, driver_opts_len), 0); ++ MOCK_SET(util_mount, 0); ++ MOCK_SET(umount2, 0); ++ ASSERT_EQ(graphdriver_init(opts), 0); + MOCK_CLEAR(util_exec_cmd); +- +- util_free_array_by_len(driver_opts, driver_opts_len); +- free(names); ++ MOCK_CLEAR(util_mount); ++ MOCK_CLEAR(umount2); + } + + void TearDown() override + { ++ MOCK_SET(umount2, 0); ++ ASSERT_EQ(graphdriver_cleanup(), 0); ++ MOCK_CLEAR(umount2); ++ + MockLibdevmapper_SetMock(nullptr); ++ MockIsuladConf_SetMock(nullptr); + std::string rm_command = "rm -rf /tmp/isulad/"; + ASSERT_EQ(system(rm_command.c_str()), 0); ++ ++ if (opts != NULL) { ++ free(opts->storage_root); ++ free(opts->storage_run_root); ++ free(opts->driver_name); ++ util_free_array_by_len(opts->driver_opts, opts->driver_opts_len); ++ free(opts); ++ } + } + + NiceMock m_libdevmapper_mock; ++ NiceMock m_isulad_conf_mock; + char data_path[PATH_MAX] = { 0x00 }; +- graphdriver driver = {.ops = nullptr, .name = "devicemapper", }; ++ struct storage_module_init_options *opts = NULL; + }; + ++TEST_F(DriverDevmapperUnitTest, test_devmapper_init) ++{ ++ // cleanup before ++ MOCK_SET(umount2, 0); ++ ASSERT_EQ(graphdriver_cleanup(), 0); ++ MOCK_CLEAR(umount2); ++ ++ std::string rm_command = "rm -rf /tmp/isulad/"; ++ ASSERT_EQ(system(rm_command.c_str()), 0); ++ std::string mk_command = "mkdir -p /tmp/isulad/data/devicemapper/mnt"; ++ ASSERT_EQ(system(mk_command.c_str()), 0); ++ char *names = static_cast(util_common_calloc_s(sizeof(struct dm_names) + strlen("isulad0-pool") + 1)); ++ struct dm_names *dname = (struct dm_names *)names; ++ dname->dev = 1; ++ dname->next = 0; ++ strcpy(names + sizeof(struct dm_names), "isulad0-pool"); ++ EXPECT_CALL(m_libdevmapper_mock, DMTaskGetNames(_)).WillOnce(Return(dname)); ++ EXPECT_CALL(m_libdevmapper_mock, DMSetDevDir(_)).WillOnce(Return(1)); ++ EXPECT_CALL(m_libdevmapper_mock, DMTaskGetDriverVersion(_, _, _)).WillOnce(Invoke(invokeDMTaskGetDriverVersion)); ++ EXPECT_CALL(m_libdevmapper_mock, DMUdevGetSyncSupport()).WillOnce(Return(1)); ++ ++ MOCK_SET_V(util_exec_cmd, invokeUtilExecCmd); ++ MOCK_SET(util_mount, 0); ++ MOCK_SET(umount2, 0); ++ ASSERT_EQ(graphdriver_init(opts), 0); ++ MOCK_CLEAR(util_exec_cmd); ++ MOCK_CLEAR(util_mount); ++ MOCK_CLEAR(umount2); ++} ++ + TEST_F(DriverDevmapperUnitTest, test_devmapper_layer_exists) + { + std::string id { "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f" }; + std::string incorrectId { "eb29745b8228e1e97c01b1d5c2554a319c00a94d8dd5746a3904222ad65a13f8" }; +- ASSERT_TRUE(devmapper_layer_exist(id.c_str(), &driver)); +- ASSERT_FALSE(devmapper_layer_exist(incorrectId.c_str(), &driver)); ++ ASSERT_TRUE(graphdriver_layer_exists(id.c_str())); ++ ASSERT_FALSE(graphdriver_layer_exists(incorrectId.c_str())); + } + + TEST_F(DriverDevmapperUnitTest, test_devmapper_create_rw) +@@ -205,11 +266,42 @@ TEST_F(DriverDevmapperUnitTest, test_devmapper_create_rw) + create_opts->storage_opt->keys = static_cast(util_common_calloc_s(sizeof(char *))); + create_opts->storage_opt->values = static_cast(util_common_calloc_s(sizeof(char *))); + create_opts->storage_opt->keys[0] = strdup("size"); +- create_opts->storage_opt->values[0] = strdup("10G"); ++ create_opts->storage_opt->values[0] = strdup("12G"); ++ create_opts->storage_opt->len = 1; ++ ++ ASSERT_EQ(graphdriver_create_rw(id.c_str(), nullptr, create_opts), 0); ++ ASSERT_TRUE(graphdriver_layer_exists(id.c_str())); ++ free_driver_create_opts(create_opts); ++} ++ ++TEST_F(DriverDevmapperUnitTest, test_devmapper_create_ro) ++{ ++ std::string id { "eb29745b8228e1e97c01b1d5c2554a319c00a94d8dd5746a3904222ad65a13f8" }; ++ struct driver_create_opts *create_opts; ++ ++ create_opts = (struct driver_create_opts *)util_common_calloc_s(sizeof(struct driver_create_opts)); ++ ASSERT_NE(create_opts, nullptr); ++ ++ create_opts->storage_opt = static_cast(util_common_calloc_s(sizeof(json_map_string_string))); ++ ASSERT_NE(create_opts->storage_opt, nullptr); ++ create_opts->storage_opt->keys = static_cast(util_common_calloc_s(sizeof(char *))); ++ create_opts->storage_opt->values = static_cast(util_common_calloc_s(sizeof(char *))); ++ create_opts->storage_opt->keys[0] = strdup("size"); ++ create_opts->storage_opt->values[0] = strdup("12G"); + create_opts->storage_opt->len = 1; + +- ASSERT_EQ(devmapper_create_rw(id.c_str(), nullptr, &driver, create_opts), 0); +- ASSERT_TRUE(devmapper_layer_exist(id.c_str(), &driver)); ++ ASSERT_EQ(graphdriver_create_ro(id.c_str(), nullptr, create_opts), 0); ++ ASSERT_TRUE(graphdriver_layer_exists(id.c_str())); ++ free_driver_create_opts(create_opts); ++} ++ ++TEST_F(DriverDevmapperUnitTest, test_devmapper_rm_layer) ++{ ++ std::string existed_id { "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f" }; ++ std::string not_existed_id { "eb29745b8228e1e97c01b1d5c2554a319c00a94d8dd5746a3904222ad65a13f8" }; ++ ++ ASSERT_EQ(graphdriver_rm_layer(existed_id.c_str()), 0); ++ ASSERT_EQ(graphdriver_rm_layer(not_existed_id.c_str()), 0); + } + + TEST_F(DriverDevmapperUnitTest, test_devmapper_mount_layer) +@@ -220,12 +312,12 @@ TEST_F(DriverDevmapperUnitTest, test_devmapper_mount_layer) + char* mount_dir = nullptr; + + MOCK_SET(util_mount, 0); +- mount_dir = devmapper_mount_layer(id.c_str(), &driver, mount_opts); ++ mount_dir = graphdriver_mount_layer(id.c_str(), mount_opts); + ASSERT_STREQ(mount_dir, merged_dir.c_str()); + MOCK_CLEAR(util_mount); + + MOCK_SET(umount2, 0); +- ASSERT_EQ(devmapper_umount_layer(id.c_str(), &driver), 0); ++ ASSERT_EQ(graphdriver_umount_layer(id.c_str()), 0); + MOCK_CLEAR(umount2); + free(mount_dir); + mount_dir = nullptr; +@@ -237,47 +329,62 @@ TEST_F(DriverDevmapperUnitTest, test_devmapper_mount_layer) + mount_opts->options_len = 1; + + MOCK_SET(util_mount, 0); +- mount_dir = devmapper_mount_layer(id.c_str(), &driver, mount_opts); ++ mount_dir = graphdriver_mount_layer(id.c_str(), mount_opts); + ASSERT_STREQ(mount_dir, merged_dir.c_str()); + MOCK_CLEAR(util_mount); + + MOCK_SET(umount2, 0); +- ASSERT_EQ(devmapper_umount_layer(id.c_str(), &driver), 0); ++ ASSERT_EQ(graphdriver_umount_layer(id.c_str()), 0); + MOCK_CLEAR(umount2); +- free(mount_opts->mount_label); +- util_free_array_by_len(mount_opts->options, mount_opts->options_len); +- free(mount_opts); +- free(mount_dir); ++ free_driver_mount_opts(mount_opts); + } + +-TEST_F(DriverDevmapperUnitTest, test_devmapper_get_layer_metadata) ++TEST_F(DriverDevmapperUnitTest, test_devmapper_get_data) + { + std::string id { "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f" }; +- json_map_string_string *map_info = static_cast(util_common_calloc_s(sizeof(json_map_string_string))); +- +- ASSERT_EQ(devmapper_get_layer_metadata(id.c_str(), &driver, map_info), 0); +- ASSERT_EQ(map_info->len, 4); +- ASSERT_STREQ(map_info->keys[0], "DeviceId"); +- ASSERT_STREQ(map_info->values[0], "4"); +- ASSERT_STREQ(map_info->keys[1], "DeviceSize"); +- ASSERT_STREQ(map_info->values[1], "10737418240"); +- ASSERT_STREQ(map_info->keys[2], "DeviceName"); +- ASSERT_STREQ(map_info->keys[3], "MergedDir"); +- ASSERT_STREQ(map_info->values[3], "/tmp/isulad/data/devicemapper/mnt/3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f/rootfs"); +- +- free_json_map_string_string(map_info); +-} + +-TEST_F(DriverDevmapperUnitTest, test_devmapper_get_driver_status) +-{ +- struct graphdriver_status *status = static_cast(util_common_calloc_s(sizeof(struct graphdriver_status))); ++ container_inspect_graph_driver *inspect = graphdriver_get_metadata(id.c_str()); ++ ASSERT_NE(inspect, nullptr); ++ ASSERT_STREQ(inspect->data->device_id, "4"); ++ ASSERT_STREQ(inspect->data->device_size, "10737418240"); ++ ASSERT_STREQ(inspect->data->merged_dir, "/tmp/isulad/data/devicemapper/mnt/3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f/rootfs"); ++ free_container_inspect_graph_driver(inspect); + + EXPECT_CALL(m_libdevmapper_mock, DMUdevGetSyncSupport()).WillOnce(Return(1)); + +- ASSERT_EQ(devmapper_get_driver_status(&driver, status), 0); ++ struct graphdriver_status *status = graphdriver_get_status(); ++ ASSERT_NE(status, nullptr); + ASSERT_STREQ(status->driver_name, "devicemapper"); +- free(status->driver_name); +- free(status->backing_fs); +- free(status->status); +- free(status); ++ free_graphdriver_status(status); ++ ++ ASSERT_EQ(devmapper_repair_lowers(nullptr, nullptr, nullptr), 0); ++ ASSERT_EQ(devmapper_get_layer_fs_info(nullptr, nullptr, nullptr), 0); + } ++ ++TEST_F(DriverDevmapperUnitTest, test_devmapper_apply_diff) ++{ ++ struct io_read_wrapper reader = {0}; ++ std::string id { "3d24ee258efc3bfe4066a1a9fb83febf6dc0b1548dfe896161533668281c9f4f" }; ++ MOCK_SET(util_mount, 0); ++ MOCK_SET(archive_unpack, 0); ++ MOCK_SET(umount2, 0); ++ EXPECT_CALL(m_isulad_conf_mock, ConfGetISuladRootDir()).WillOnce(Return(util_strdup_s("/tmp/isulad"))); ++ ASSERT_EQ(graphdriver_apply_diff(id.c_str(), &reader), 0); ++ MOCK_CLEAR(archive_unpack); ++ MOCK_CLEAR(util_mount); ++ MOCK_CLEAR(umount2); ++} ++ ++TEST_F(DriverDevmapperUnitTest, test_wrapper_devmapper) ++{ ++ ASSERT_STREQ(dev_strerror(ERR_TASK_RUN), "Task run error"); ++ ASSERT_STREQ(dev_strerror(ERR_TASK_SET_COOKIE), "Task set cookie error"); ++ ASSERT_STREQ(dev_strerror(ERR_NIL_COOKIE), "cookie ptr can't be nil"); ++ ASSERT_STREQ(dev_strerror(ERR_TASK_SET_ADD_NODE), "Task add dm node failed"); ++ ASSERT_STREQ(dev_strerror(ERR_BUSY), "Device busy"); ++ ASSERT_STREQ(dev_strerror(ERR_DEVICE_ID_EXISTS), "Device exists already"); ++ ASSERT_STREQ(dev_strerror(ERR_ENXIO), "No such device of address"); ++ ASSERT_STREQ(dev_strerror(ERR_TASK_ADD_TARGET), "Task add target device error"); ++ ASSERT_STREQ(dev_strerror(ERR_TASK_DEFERRED_REMOVE), "dm_task_deferred_remove failed"); ++ ASSERT_STREQ(dev_strerror(100), "Unknown error"); ++} +\ No newline at end of file +-- +2.42.0 + diff --git a/0046-2292-bugfix-for-run.sh-and-add-build-notify-msg-for-.patch b/0046-2292-bugfix-for-run.sh-and-add-build-notify-msg-for-.patch new file mode 100644 index 0000000..3831382 --- /dev/null +++ b/0046-2292-bugfix-for-run.sh-and-add-build-notify-msg-for-.patch @@ -0,0 +1,56 @@ +From d813e654b5b964f79857df3c9130f174443a76be Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Mon, 4 Dec 2023 09:44:42 +0000 +Subject: [PATCH 46/64] !2292 bugfix for run.sh and add build notify msg for + ENABLE_GRPC_REMOTE_CONNECT * bugfix for run.sh and add build notify msg for + ENABLE_GRPC_REMOTE_CONNECT + +--- + CI/test_cases/container_cases/run.sh | 6 +++--- + cmake/options.cmake | 1 + + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/CI/test_cases/container_cases/run.sh b/CI/test_cases/container_cases/run.sh +index 8ea3e514..1bfd388b 100755 +--- a/CI/test_cases/container_cases/run.sh ++++ b/CI/test_cases/container_cases/run.sh +@@ -27,7 +27,8 @@ function do_test_t() + { + tid=`isula run --runtime $1 -tid --name hostname busybox` + chostname=`isula exec -it $tid hostname` +- fn_check_eq "$chostname" "${tid:0:12}" "default hostname is id of container" ++ clean_hostname=$(echo "$hostname" | sed 's/[\x01-\x1F\x7F]//g') ++ fn_check_eq "${clean_hostname}" "${tid:0:12}" "default hostname is not id of container" + isula exec -it hostname env | grep HOSTNAME + fn_check_eq "$?" "0" "check HOSTNAME env failed" + isula stop -t 0 $tid +@@ -149,13 +150,12 @@ function do_run_remote_test_t() + + isula run --runtime $1 -ti -H "$config" --name $containername busybox xxx + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed check invalid run ${containername} remote" && ((ret++)) +- testcontainer $containername exited ++ + isula rm -f -H "$config" $containername + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to rm container remote" && ((ret++)) + + isula run --runtime $1 -ti -H "$config" --name $containername busybox /bin/sh -c 'echo "hello"' | grep hello + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to run ${containername} remote" && ((ret++)) +- testcontainer $containername exited + + isula rm -f -H "$config" $containername + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to rm container remote" && ((ret++)) +diff --git a/cmake/options.cmake b/cmake/options.cmake +index aeb24662..bf7db93a 100644 +--- a/cmake/options.cmake ++++ b/cmake/options.cmake +@@ -110,6 +110,7 @@ option(ENABLE_GRPC_REMOTE_CONNECT "enable gRPC remote connect" OFF) + if (ENABLE_GRPC_REMOTE_CONNECT STREQUAL "ON") + add_definitions(-DENABLE_GRPC_REMOTE_CONNECT=1) + set(ENABLE_GRPC_REMOTE_CONNECT 1) ++ message("${Green}-- enable gRPC remote connect${ColourReset}") + endif() + + option(ENABLE_SHIM_V2 "enable shim v2 runtime" OFF) +-- +2.42.0 + diff --git a/0047-2295-keep-the-service-status-unchanged-after-iSulad-.patch b/0047-2295-keep-the-service-status-unchanged-after-iSulad-.patch new file mode 100644 index 0000000..661dc88 --- /dev/null +++ b/0047-2295-keep-the-service-status-unchanged-after-iSulad-.patch @@ -0,0 +1,251 @@ +From 98825c56135aeeb02f50a5eec5896d39d3ea649f Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Wed, 6 Dec 2023 01:56:52 +0000 +Subject: [PATCH 47/64] !2295 keep the service status unchanged after iSulad + service upgrade * keep the service status unchanged after iSulad service + upgrade and + +--- + iSulad.spec | 121 +++++++++++++++++++++++++++------------------------- + 1 file changed, 62 insertions(+), 59 deletions(-) + +diff --git a/iSulad.spec b/iSulad.spec +index 6be2067d..0efbf043 100644 +--- a/iSulad.spec ++++ b/iSulad.spec +@@ -1,24 +1,23 @@ + %global _version 2.1.4 +-%global _release 1 ++%global _release 2 + %global is_systemd 1 + %global enable_criv1 1 + %global enable_shimv2 1 +-%global enable_embedded 1 ++%global is_embedded 1 ++%global cpp_std 17 + + Name: iSulad + Version: %{_version} + Release: %{_release} + Summary: Lightweight Container Runtime Daemon + License: Mulan PSL v2 +-URL: isulad +-Source: iSulad-2.1.tar.gz ++URL: https://gitee.com/openeuler/iSulad ++Source: https://gitee.com/openeuler/iSulad/repository/archive/v%{version}.tar.gz + BuildRoot: {_tmppath}/iSulad-%{version} +-ExclusiveArch: x86_64 aarch64 + + %ifarch x86_64 aarch64 + Provides: libhttpclient.so()(64bit) + Provides: libisula_client.so()(64bit) +-Provides: libisulad_img.so()(64bit) + Provides: libisulad_tools.so()(64bit) + %endif + +@@ -33,40 +32,56 @@ Requires(preun): chkconfig + Requires(preun): initscripts + %endif + +-%if 0%{?enable_embedded} ++%if 0%{?is_embedded} + BuildRequires: sqlite-devel +-Requires: sqlite ++Requires: sqlite + %endif + +-%if 0%{?enable_shimv2} +-BuildRequires: lib-shim-v2-devel +-Requires: lib-shim-v2 ++%if %{defined openeuler} ++BuildRequires: gtest-devel gmock-devel + %endif + +-BuildRequires: cmake gcc-c++ lxc-devel lcr-devel yajl-devel libisula-devel +-BuildRequires: grpc-plugins grpc-devel protobuf-devel +-BuildRequires: libcurl-devel libarchive-devel device-mapper-devel ++%define lcrver_lower 2.1.3-0 ++%define lcrver_upper 2.1.4-0 ++ ++BuildRequires: libisula-devel > %{lcrver_lower} libisula-devel < %{lcrver_upper} ++BuildRequires: cmake gcc-c++ yajl-devel ++BuildRequires: grpc grpc-plugins grpc-devel protobuf-devel ++BuildRequires: libcurl libcurl-devel libarchive-devel device-mapper-devel + BuildRequires: http-parser-devel +-BuildRequires: libselinux-devel libwebsockets-devel ++BuildRequires: libseccomp-devel libcap-devel libselinux-devel libwebsockets libwebsockets-devel + BuildRequires: systemd-devel git ++BuildRequires: libevhtp-devel libevent-devel ++%if 0%{?enable_shimv2} ++BuildRequires: lib-shim-v2 lib-shim-v2-devel ++%endif ++ + +-Requires: libisula lxc +-Requires: grpc libcurl http-parser +-Requires: libselinux libwebsockets libarchive device-mapper ++Requires: libisula > %{lcrver_lower} libisula < %{lcrver_upper} ++Requires: grpc protobuf ++Requires: libcurl ++Requires: http-parser libseccomp ++Requires: libcap libselinux libwebsockets libarchive device-mapper + Requires: systemd ++Requires: (docker-runc or runc) ++BuildRequires: libevhtp libevent ++%if 0%{?enable_shimv2} ++Requires: lib-shim-v2 ++%endif + + %description + This is a umbrella project for gRPC-services based Lightweight Container + Runtime Daemon, written by C. + + %prep +-%autosetup -c -n iSulad-%{version} ++%autosetup -n iSulad-v%{_version} -Sgit -p1 + + %build + mkdir -p build + cd build + %cmake \ + -DDEBUG=ON \ ++ -DCMAKE_SKIP_RPATH=TRUE \ + -DLIB_INSTALL_DIR=%{_libdir} \ + -DCMAKE_INSTALL_PREFIX=/usr \ + %if 0%{?enable_criv1} +@@ -76,36 +91,47 @@ cd build + %if 0%{?enable_shimv2} + -DENABLE_SHIM_V2=ON \ + %endif ++%if %{defined openeuler} ++ -DENABLE_UT=OFF \ ++%endif ++ -DENABLE_GRPC_REMOTE_CONNECT=OFF \ ++ -DENABLE_GRPC=ON \ ++ -DCMAKE_CXX_STANDARD=%{cpp_std} \ + ../ ++ ++sed -i "10 a\# undef linux" grpc/src/api/services/cri/v1alpha/api.pb.h ++%if 0%{?enable_criv1} ++sed -i "10 a\# undef linux" grpc/src/api/services/cri/v1/api_v1.pb.h ++%endif ++ + %make_build + ++%check ++%if %{defined openeuler} ++cd build ++# registry_images_ut and volume_ut must run with root user ++ctest -E "registry_images_ut|volume_ut" ++%endif ++ + %install + rm -rf %{buildroot} + cd build + install -d $RPM_BUILD_ROOT/%{_libdir} +-install -m 0644 ./src/libisula_client.so %{buildroot}/%{_libdir}/libisula_client.so +-install -m 0644 ./src/utils/http/libhttpclient.so %{buildroot}/%{_libdir}/libhttpclient.so +-chrpath -d ./src/libisulad_tools.so +-install -m 0644 ./src/libisulad_tools.so %{buildroot}/%{_libdir}/libisulad_tools.so +-chrpath -d ./src/daemon/modules/image/libisulad_img.so +-install -m 0644 ./src/daemon/modules/image/libisulad_img.so %{buildroot}/%{_libdir}/libisulad_img.so +-chmod +x %{buildroot}/%{_libdir}/libisula_client.so +-chmod +x %{buildroot}/%{_libdir}/libhttpclient.so +-chmod +x %{buildroot}/%{_libdir}/libisulad_img.so ++install -m 0755 ./src/libisula_client.so %{buildroot}/%{_libdir}/libisula_client.so ++install -m 0755 ./src/utils/http/libhttpclient.so %{buildroot}/%{_libdir}/libhttpclient.so ++install -m 0755 ./src/libisulad_tools.so %{buildroot}/%{_libdir}/libisulad_tools.so + + install -d $RPM_BUILD_ROOT/%{_libdir}/pkgconfig + install -m 0640 ./conf/isulad.pc %{buildroot}/%{_libdir}/pkgconfig/isulad.pc + + install -d $RPM_BUILD_ROOT/%{_bindir} ++ + install -m 0755 ./src/isula %{buildroot}/%{_bindir}/isula + install -m 0755 ./src/isulad-shim %{buildroot}/%{_bindir}/isulad-shim +-install -m 0755 ./src/isulad %{buildroot}/%{_bindir}/isulad +-chrpath -d ./src/isula +-chrpath -d ./src/isulad-shim +-chrpath -d ./src/isulad ++ ++install -m 0755 ./src/isulad %{buildroot}/%{_bindir}/isulad + + install -d $RPM_BUILD_ROOT/%{_includedir}/isulad +-install -m 0644 ../src/daemon/modules/api/image_api.h %{buildroot}/%{_includedir}/isulad/image_api.h + + install -d $RPM_BUILD_ROOT/%{_sysconfdir}/isulad + install -m 0640 ../src/contrib/config/daemon.json %{buildroot}/%{_sysconfdir}/isulad/daemon.json +@@ -134,8 +160,6 @@ install -d $RPM_BUILD_ROOT/%{_initddir} + install -p -m 0640 ../src/contrib/init/isulad.init $RPM_BUILD_ROOT/%{_initddir}/isulad.init + %endif + +-install -d $RPM_BUILD_ROOT/usr/share/bash-completion/completions +-install -p -m 0644 ../src/contrib/completion/isula $RPM_BUILD_ROOT/usr/share/bash-completion/completions/isula + %clean + rm -rf %{buildroot} + +@@ -143,19 +167,17 @@ rm -rf %{buildroot} + # support update from lcrd to isulad, will remove in next version + if [ "$1" = "2" ]; then + %if 0%{?is_systemd} +-systemctl stop lcrd +-systemctl disable lcrd ++systemctl stop lcrd &>/dev/null ++systemctl disable lcrd &>/dev/null + if [ -e %{_sysconfdir}/isulad/daemon.json ];then + sed -i 's#/etc/default/lcrd/hooks#/etc/default/isulad/hooks#g' %{_sysconfdir}/isulad/daemon.json + fi + %else +-/sbin/chkconfig --del lcrd ++/sbin/chkconfig --del lcrd &>/dev/null + %endif + fi + + %post +-source /usr/share/bash-completion/completions/isula +- + if ! getent group isula > /dev/null; then + groupadd --system isula + fi +@@ -174,12 +196,6 @@ if [ -e %{_unitdir}/lcrd.service.rpmsave ]; then + mv %{_unitdir}/lcrd.service.rpmsave %{_unitdir}/isulad.service + sed -i 's/lcrd/isulad/g' %{_unitdir}/isulad.service + fi +-systemctl status isulad | grep 'Active:' | grep 'running' +-if [ $? -eq 0 ]; then +- systemctl restart isulad +-else +- systemctl start isulad +-fi + %else + /sbin/service isulad status | grep 'Active:' | grep 'running' + if [ $? -eq 0 ]; then +@@ -226,7 +242,6 @@ fi + %{_initddir}/isulad.init + %attr(0640,root,root) %{_initddir}/isulad.init + %endif +-%{_includedir}/isulad/* + %attr(0755,root,root) %{_libdir}/pkgconfig + %attr(0640,root,root) %{_libdir}/pkgconfig/isulad.pc + %defattr(0755,root,root,0755) +@@ -242,17 +257,5 @@ fi + %else + %config(noreplace,missingok) %{_initddir}/isulad.init + %endif +-/usr/share/bash-completion/completions/isula + + %changelog +-* Tue Sep 10 2020 openEuler Buildteam - 2.0.5-20200910.140350.git72990229 +-- Type:enhancement +-- ID:NA +-- SUG:NA +-- DESC: add chrpath +- +-* Mon Aug 03 2020 openEuler Buildteam - 2.0.3-20200803.130854.git0c7dc28a +-- Type:enhancement +-- ID:NA +-- SUG:NA +-- DESC: add debug packages +-- +2.42.0 + diff --git a/0048-modify-attach-socket-name.patch b/0048-modify-attach-socket-name.patch new file mode 100644 index 0000000..e1eb159 --- /dev/null +++ b/0048-modify-attach-socket-name.patch @@ -0,0 +1,40 @@ +From c01b761e14e6b4ea6745688e47b255f17ba26055 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Wed, 6 Dec 2023 15:15:32 +0800 +Subject: [PATCH 48/64] modify attach socket name + +Signed-off-by: zhongtao +--- + src/cmd/isulad-shim/common.h | 2 +- + src/daemon/modules/runtime/isula/isula_rt_ops.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/cmd/isulad-shim/common.h b/src/cmd/isulad-shim/common.h +index 2020a799..c4f86d24 100644 +--- a/src/cmd/isulad-shim/common.h ++++ b/src/cmd/isulad-shim/common.h +@@ -60,7 +60,7 @@ extern "C" { + #define CONTAINER_ACTION_REBOOT 129 + #define CONTAINER_ACTION_SHUTDOWN 130 + +-#define ATTACH_SOCKET "attach_socket.sock" ++#define ATTACH_SOCKET "attach.sock" + #define ATTACH_LOG_NAME "attach-log.json" + #define ATTACH_DETACH_MSG "read escape sequence" + #define MAX_ATTACH_NUM 16 +diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c +index 3950ff4a..fbb779f7 100644 +--- a/src/daemon/modules/runtime/isula/isula_rt_ops.c ++++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c +@@ -57,7 +57,7 @@ + + #define SHIM_BINARY "isulad-shim" + #define RESIZE_FIFO_NAME "resize_fifo" +-#define ATTACH_SOCKET "attach_socket.sock" ++#define ATTACH_SOCKET "attach.sock" + #define SHIM_LOG_SIZE ((BUFSIZ - 100) / 2) + #define RESIZE_DATA_SIZE 100 + #define PID_WAIT_TIME 120 +-- +2.42.0 + diff --git a/0049-2298-bugfix-for-hook_ignore_poststart_error-run-in-o.patch b/0049-2298-bugfix-for-hook_ignore_poststart_error-run-in-o.patch new file mode 100644 index 0000000..4c90ed4 --- /dev/null +++ b/0049-2298-bugfix-for-hook_ignore_poststart_error-run-in-o.patch @@ -0,0 +1,110 @@ +From 94122c5752936b4f5db14521cdd0f39a3dec6851 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Thu, 7 Dec 2023 03:32:15 +0000 +Subject: [PATCH 49/64] !2298 bugfix for hook_ignore_poststart_error run in oci + runtime * bugfix for hook_ignore_poststart_error run in oci runtime + +--- + .../hook_ignore_poststart_error.sh | 70 +++++++++++++------ + 1 file changed, 50 insertions(+), 20 deletions(-) + +diff --git a/CI/test_cases/container_cases/hook_ignore_poststart_error.sh b/CI/test_cases/container_cases/hook_ignore_poststart_error.sh +index 8c636f7e..38b6f021 100755 +--- a/CI/test_cases/container_cases/hook_ignore_poststart_error.sh ++++ b/CI/test_cases/container_cases/hook_ignore_poststart_error.sh +@@ -24,6 +24,48 @@ source ../helpers.sh + + test_data_path=$(realpath $curr_path/test_data) + ++# $1 hook process ++# $2 container id ++# $3 expect container status ++# $4 process statement ++function test_kill_hook() ++{ ++ for a in `seq 20` ++ do ++ bpid=`ps aux | grep "$1" | grep -v grep | awk '{print $2}'` ++ if [ "x" != "x$bpid" ];then ++ kill -9 $bpid ++ break ++ else ++ sleep .5 ++ continue ++ fi ++ done ++ ++ if [ "x" != "x$4" ];then ++ for a in `seq 20` ++ do ++ bpid=`ps aux | grep "$4" | grep -v grep | awk '{print $2}'` ++ if [ "x" != "x$bpid" ];then ++ kill -9 $bpid ++ break ++ else ++ sleep .5 ++ continue ++ fi ++ done ++ fi ++ ++ status=`isula inspect -f '{{json .State.Status}}' $2` ++ if [ "$status" == "$3" ];then ++ echo "get right status" ++ return 0 ++ else ++ echo "expect $2 $3, but get $status" ++ return 1 ++ fi ++} ++ + function test_hook_ignore_poststart_error_spec() + { + local ret=0 +@@ -42,27 +84,15 @@ function test_hook_ignore_poststart_error_spec() + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - missing list image: ${image}" && ((ret++)) + + isula run -n $CONT -itd --runtime $runtime --hook-spec ${test_data_path}/oci_hook_poststart_check.json ${image} & +- +- for a in `seq 20` +- do +- bpid=`ps aux | grep "poststart.sh" | grep -v grep | awk '{print $2}'` +- if [ "x" != "x$bpid" ];then +- kill -9 $bpid +- break +- else +- sleep .5 +- continue +- fi +- done +- +- status=`isula inspect -f '{{json .State.Status}}' $CONT` +- if [ "$status" == "\"running\"" ];then +- echo "get right status" ++ ++ # when runc container run poststart hook, the process structure is different from lxc ++ if [ $runtime == "lcr" ]; then ++ test_kill_hook "poststart.sh" $CONT \"running\" + else +- echo "expect $CONT running, but get $status" +- ret++ ++ test_kill_hook "poststart.sh" $CONT \"exited\" "sleep 300" + fi +- ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to test kill hook: ${image}" && ((ret++)) ++ + isula stop -t 0 ${CONT} + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to stop ${CONT}" && ((ret++)) + +@@ -77,7 +107,7 @@ declare -i ans=0 + + for element in ${RUNTIME_LIST[@]}; + do +- test_hook_ignore_poststart_error_spec $1 || ((ans++)) ++ test_hook_ignore_poststart_error_spec $element || ((ans++)) + done + + show_result ${ans} "${curr_path}/${0}" +-- +2.42.0 + diff --git a/0050-2304-remove-build-and-test-in-coverage.patch b/0050-2304-remove-build-and-test-in-coverage.patch new file mode 100644 index 0000000..8fccf01 --- /dev/null +++ b/0050-2304-remove-build-and-test-in-coverage.patch @@ -0,0 +1,28 @@ +From c2e9919ec8612d6e811644ec8aacf53cec0c4f20 Mon Sep 17 00:00:00 2001 +From: jake +Date: Tue, 12 Dec 2023 08:55:30 +0000 +Subject: [PATCH 50/64] !2304 remove build and test in coverage * remove build + and test in coverage + +--- + CI/generate_gcov.sh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/CI/generate_gcov.sh b/CI/generate_gcov.sh +index 153c9f5a..76bf382b 100755 +--- a/CI/generate_gcov.sh ++++ b/CI/generate_gcov.sh +@@ -31,8 +31,8 @@ ctest + lcov --directory . --capture --output-file coverage.info --rc lcov_branch_coverage=1 + # Remove std/build files + lcov --remove coverage.info '/usr/*' -o coverage.info --rc lcov_branch_coverage=1 +-lcov --remove coverage.info 'build/*' -o coverage.info --rc lcov_branch_coverage=1 +-lcov --remove coverage.info 'test/*' -o coverage.info --rc lcov_branch_coverage=1 ++lcov --remove coverage.info "$ISULAD_SRC_PATH/build/*" -o coverage.info --rc lcov_branch_coverage=1 ++lcov --remove coverage.info "$ISULAD_SRC_PATH/test/*" -o coverage.info --rc lcov_branch_coverage=1 + + # Generate html + genhtml --ignore-errors source -o $GCOV_RESULT_PATH/coverage coverage.info --branch-coverage --rc lcov_branch_coverage=1 +-- +2.42.0 + diff --git a/0051-2303-use-a-timeout-epoll-loop-to-ensure-complete-dat.patch b/0051-2303-use-a-timeout-epoll-loop-to-ensure-complete-dat.patch new file mode 100644 index 0000000..87e528a --- /dev/null +++ b/0051-2303-use-a-timeout-epoll-loop-to-ensure-complete-dat.patch @@ -0,0 +1,197 @@ +From 7d1b8d25468528a59318430d50d839032f2c1a07 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Tue, 12 Dec 2023 12:26:32 +0000 +Subject: [PATCH 51/64] !2303 use a timeout epoll loop to ensure complete data + reception * use a timeout epoll loop to ensure complete data reception + +--- + src/cmd/isulad-shim/process.c | 105 +++++++++------------------------- + src/cmd/isulad-shim/process.h | 1 - + 2 files changed, 26 insertions(+), 80 deletions(-) + +diff --git a/src/cmd/isulad-shim/process.c b/src/cmd/isulad-shim/process.c +index e8cb9b32..97524f1a 100644 +--- a/src/cmd/isulad-shim/process.c ++++ b/src/cmd/isulad-shim/process.c +@@ -169,6 +169,7 @@ static int get_exec_winsize(const char *buf, struct winsize *wsize) + + static int sync_exit_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t *descr) + { ++ isula_epoll_remove_handler(descr, fd); + return EPOLL_LOOP_HANDLE_CLOSE; + } + +@@ -364,23 +365,14 @@ static int stdout_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t + int r_count = 0; + int w_count = 0; + +- if (events & EPOLLHUP) { +- return EPOLL_LOOP_HANDLE_CLOSE; +- } +- +- if (!(events & EPOLLIN)) { +- return EPOLL_LOOP_HANDLE_CONTINUE; +- } +- + (void)memset(p->buf, 0, DEFAULT_IO_COPY_BUF); + +- if (p->block_read) { +- r_count = isula_file_read_nointr(fd, p->buf, DEFAULT_IO_COPY_BUF); +- } else { +- r_count = read(fd, p->buf, DEFAULT_IO_COPY_BUF); +- } +- if (r_count <= 0) { +- return EPOLL_LOOP_HANDLE_CLOSE; ++ r_count = isula_file_read_nointr(fd, p->buf, DEFAULT_IO_COPY_BUF); ++ if (r_count <= 0 ) { ++ isula_epoll_remove_handler(descr, fd); ++ // fd cannot be closed here, which will cause the container process to exit abnormally ++ // due to terminal fd receiving the sighup signal. ++ return EPOLL_LOOP_HANDLE_CONTINUE; + } + + shim_write_container_log_file(p->terminal, STDID_OUT, p->buf, r_count); +@@ -419,23 +411,14 @@ static int stderr_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t + int r_count = 0; + int w_count = 0; + +- if (events & EPOLLHUP) { +- return EPOLL_LOOP_HANDLE_CLOSE; +- } +- +- if (!(events & EPOLLIN)) { +- return EPOLL_LOOP_HANDLE_CONTINUE; +- } +- + (void)memset(p->buf, 0, DEFAULT_IO_COPY_BUF); + +- if (p->block_read) { +- r_count = isula_file_read_nointr(fd, p->buf, DEFAULT_IO_COPY_BUF); +- } else { +- r_count = read(fd, p->buf, DEFAULT_IO_COPY_BUF); +- } +- if (r_count <= 0) { +- return EPOLL_LOOP_HANDLE_CLOSE; ++ r_count = isula_file_read_nointr(fd, p->buf, DEFAULT_IO_COPY_BUF); ++ if (r_count <= 0 ) { ++ isula_epoll_remove_handler(descr, fd); ++ // fd cannot be closed here, which will cause the container process to exit abnormally ++ // due to terminal fd receiving the sighup signal. ++ return EPOLL_LOOP_HANDLE_CONTINUE; + } + + shim_write_container_log_file(p->terminal, STDID_ERR, p->buf, r_count); +@@ -474,18 +457,11 @@ static int resize_cb(int fd, uint32_t events, void *cbdata, isula_epoll_descr_t + int r_count = 0; + int resize_fd = -1; + +- if (events & EPOLLHUP) { +- return EPOLL_LOOP_HANDLE_CLOSE; +- } +- +- if (!(events & EPOLLIN)) { +- return EPOLL_LOOP_HANDLE_CONTINUE; +- } +- + (void)memset(p->buf, 0, DEFAULT_IO_COPY_BUF); + r_count = isula_file_read_nointr(fd, p->buf, DEFAULT_IO_COPY_BUF); + if (r_count <= 0) { +- return EPOLL_LOOP_HANDLE_CLOSE; ++ close(fd); ++ return EPOLL_LOOP_HANDLE_CONTINUE; + } + + resize_fd = p->recv_fd; +@@ -915,8 +891,6 @@ static int open_generic_io(process_t *p, isula_epoll_descr_t *descr) + static void *io_epoll_loop(void *data) + { + int ret = 0; +- int fd_out = -1; +- int fd_err = -1; + process_t *p = (process_t *)data; + isula_epoll_descr_t descr; + +@@ -953,49 +927,23 @@ static void *io_epoll_loop(void *data) + + (void)sem_post(&p->sem_mainloop); + ++ // th frist epoll_loop will exit in the following scenarios: ++ // 1. Receive sync fd event ++ // 2. stdin fd receive EPOLLHUP event ++ // 3. stdin fd read failed + ret = isula_epoll_loop(&descr, -1); + if (ret != 0) { + write_message(ERR_MSG, "epoll loop failed"); + exit(EXIT_FAILURE); + } + +- // in order to avoid data loss, set fd non-block and read it +- p->block_read = false; +- if (p->state->terminal) { +- fd_out = p->recv_fd; +- } else { +- fd_out = p->shim_io->out; +- fd_err = p->shim_io->err; +- } +- +- if (fd_out > 0) { +- ret = isula_set_non_block(fd_out); +- if (ret != SHIM_OK) { +- write_message(ERR_MSG, "set fd %d non_block failed:%d", fd_out, SHIM_SYS_ERR(errno)); +- exit(EXIT_FAILURE); +- } +- +- for (;;) { +- ret = stdout_cb(fd_out, EPOLLIN, p, &descr); +- if (ret == EPOLL_LOOP_HANDLE_CLOSE) { +- break; +- } +- } +- } +- +- if (fd_err > 0) { +- ret = isula_set_non_block(fd_err); +- if (ret != SHIM_OK) { +- write_message(ERR_MSG, "set fd %d non_block failed:%d", fd_err, SHIM_SYS_ERR(errno)); +- exit(EXIT_FAILURE); +- } +- +- for (;;) { +- ret = stderr_cb(fd_err, EPOLLIN, p, &descr); +- if (ret == EPOLL_LOOP_HANDLE_CLOSE) { +- break; +- } +- } ++ // use a timeout epoll loop to ensure complete data reception ++ // th second epoll_loop will exit in the following scenarios: ++ // 1. both stdout fd and stderr fd failed to read ++ // 2. no event received within 100 milliseconds ++ ret = isula_epoll_loop(&descr, 100); ++ if (ret != 0) { ++ write_message(ERR_MSG, "Repeat the epoll loop to ensure that all data is transferred"); + } + + return NULL; +@@ -1220,7 +1168,6 @@ process_t *new_process(char *id, char *bundle, char *runtime) + p->bundle = bundle; + p->runtime = runtime; + p->state = p_state; +- p->block_read = true; + p->console_sock_path = NULL; + p->exit_fd = -1; + p->io_loop_fd = -1; +diff --git a/src/cmd/isulad-shim/process.h b/src/cmd/isulad-shim/process.h +index 5607316c..32ba7366 100644 +--- a/src/cmd/isulad-shim/process.h ++++ b/src/cmd/isulad-shim/process.h +@@ -55,7 +55,6 @@ typedef struct process { + int sync_fd; + int listen_fd; + int recv_fd; +- bool block_read; + log_terminal *terminal; + stdio_t *stdio; // shim to on runtime side, in:r out/err: w + stdio_t *shim_io; // shim io on isulad side, in: w out/err: r +-- +2.42.0 + diff --git a/0052-modify-the-default-value-of-ISULAD_TMPDIR-to-var-lib.patch b/0052-modify-the-default-value-of-ISULAD_TMPDIR-to-var-lib.patch new file mode 100644 index 0000000..cf0c729 --- /dev/null +++ b/0052-modify-the-default-value-of-ISULAD_TMPDIR-to-var-lib.patch @@ -0,0 +1,170 @@ +From 06d42781cbfc3d9baa7155b480e22b9f4164ab91 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Tue, 12 Dec 2023 20:24:57 +0800 +Subject: [PATCH 52/64] modify the default value of ISULAD_TMPDIR to + /var/lib/isulad + +Signed-off-by: zhongtao +--- + src/cmd/isulad/main.c | 13 +++++++------ + src/common/constants.h | 2 ++ + src/contrib/config/iSulad.sysconfig | 4 ++-- + .../modules/container/leftover_cleanup/cleanup.c | 6 +++--- + src/daemon/modules/image/oci/utils_images.c | 2 +- + src/utils/cutils/utils_verify.c | 5 +++++ + src/utils/cutils/utils_verify.h | 2 ++ + src/utils/tar/util_archive.c | 9 +++++---- + 8 files changed, 27 insertions(+), 16 deletions(-) + +diff --git a/src/cmd/isulad/main.c b/src/cmd/isulad/main.c +index 95454e2a..d33e4004 100644 +--- a/src/cmd/isulad/main.c ++++ b/src/cmd/isulad/main.c +@@ -1295,8 +1295,8 @@ static int ensure_isulad_tmpdir_security() + char *isulad_tmp_dir = NULL; + + isulad_tmp_dir = getenv("ISULAD_TMPDIR"); +- if (!util_valid_str(isulad_tmp_dir)) { +- isulad_tmp_dir = "/tmp"; ++ if (!util_valid_isulad_tmpdir(isulad_tmp_dir)) { ++ isulad_tmp_dir = DEFAULT_ISULAD_TMPDIR; + } + + if (do_ensure_isulad_tmpdir_security(isulad_tmp_dir) != 0) { +@@ -1304,14 +1304,15 @@ static int ensure_isulad_tmpdir_security() + return -1; + } + +- if (strcmp(isulad_tmp_dir, "/tmp") == 0) { ++ if (strcmp(isulad_tmp_dir, DEFAULT_ISULAD_TMPDIR) == 0) { + return 0; + } + + // No matter whether ISULAD_TMPDIR is set or not, +- // ensure the "/tmp" directory is a safe directory +- if (do_ensure_isulad_tmpdir_security("/tmp") != 0) { +- WARN("Failed to ensure the /tmp directory is a safe directory"); ++ // ensure the DEFAULT_ISULAD_TMPDIR directory is a safe directory ++ // TODO: if isula is no longer tarred in the future, we can delete it. ++ if (do_ensure_isulad_tmpdir_security(DEFAULT_ISULAD_TMPDIR) != 0) { ++ WARN("Failed to ensure the default ISULAD_TMPDIR : %s directory is a safe directory", DEFAULT_ISULAD_TMPDIR); + } + + return 0; +diff --git a/src/common/constants.h b/src/common/constants.h +index 5f12ae25..27d4956e 100644 +--- a/src/common/constants.h ++++ b/src/common/constants.h +@@ -129,6 +129,8 @@ extern "C" { + + #define OCI_IMAGE_GRAPH_ROOTPATH_NAME "storage" + ++#define DEFAULT_ISULAD_TMPDIR "/var/lib/isulad" ++ + #ifdef ENABLE_GRPC_REMOTE_CONNECT + #define DEFAULT_TCP_HOST "tcp://localhost:2375" + #define DEFAULT_TLS_HOST "tcp://localhost:2376" +diff --git a/src/contrib/config/iSulad.sysconfig b/src/contrib/config/iSulad.sysconfig +index 43ba7cbd..25099480 100644 +--- a/src/contrib/config/iSulad.sysconfig ++++ b/src/contrib/config/iSulad.sysconfig +@@ -22,5 +22,5 @@ + #SYSMONITOR_OPTIONS='-H tcp://127.0.0.1:2375 --tlsverify --tlscacert=/root/.iSulad/ca.pem --tlscert=/root/.iSulad/cert.pem --tlskey=/root/.iSulad/key.pem' + + # Location used for temporary files, such as those created by isula load and pull operations. +-# Default is /var/tmp. Can be overridden by setting the following env variable. +-# ISULAD_TMPDIR=/var/tmp ++# Default is /var/lib/isulad. Can be overridden by setting the following env variable. ++# ISULAD_TMPDIR=/var/lib/isulad +diff --git a/src/daemon/modules/container/leftover_cleanup/cleanup.c b/src/daemon/modules/container/leftover_cleanup/cleanup.c +index 9a38ffc2..af5f0eee 100644 +--- a/src/daemon/modules/container/leftover_cleanup/cleanup.c ++++ b/src/daemon/modules/container/leftover_cleanup/cleanup.c +@@ -203,12 +203,12 @@ void do_isulad_tmpdir_cleaner(void) + char *isula_tmp_dir = NULL; + + isula_tmp_dir = getenv("ISULAD_TMPDIR"); +- if (util_valid_str(isula_tmp_dir)) { ++ if (util_valid_isulad_tmpdir(isula_tmp_dir)) { + cleanup_path(isula_tmp_dir); + } + // No matter whether ISULAD_TMPDIR is set or not, +- // clean up the "/tmp" directory to prevent the mount point from remaining +- cleanup_path("/tmp"); ++ // clean up the DEFAULT_ISULAD_TMPDIR directory to prevent the mount point from remaining ++ cleanup_path(DEFAULT_ISULAD_TMPDIR); + + return; + } +diff --git a/src/daemon/modules/image/oci/utils_images.c b/src/daemon/modules/image/oci/utils_images.c +index f92ee59a..d94388bd 100644 +--- a/src/daemon/modules/image/oci/utils_images.c ++++ b/src/daemon/modules/image/oci/utils_images.c +@@ -595,7 +595,7 @@ char *oci_get_isulad_tmpdir(const char *root_dir) + } + + env_dir = getenv("ISULAD_TMPDIR"); +- if (util_valid_str(env_dir)) { ++ if (util_valid_isulad_tmpdir(env_dir)) { + isulad_tmpdir = util_path_join(env_dir, "isulad_tmpdir"); + } else { + isulad_tmpdir = util_path_join(root_dir, "isulad_tmpdir"); +diff --git a/src/utils/cutils/utils_verify.c b/src/utils/cutils/utils_verify.c +index f4ce3199..7f2db48b 100644 +--- a/src/utils/cutils/utils_verify.c ++++ b/src/utils/cutils/utils_verify.c +@@ -744,6 +744,11 @@ bool util_valid_volume_name(const char *name) + return util_reg_match(patten, name) == 0; + } + ++bool util_valid_isulad_tmpdir(const char *dir) ++{ ++ return util_valid_str(dir) && strcmp(dir, "/tmp") != 0; ++} ++ + #ifdef ENABLE_IMAGE_SEARCH + bool util_valid_search_name(const char *name) + { +diff --git a/src/utils/cutils/utils_verify.h b/src/utils/cutils/utils_verify.h +index 54d1ce71..bafd2a82 100644 +--- a/src/utils/cutils/utils_verify.h ++++ b/src/utils/cutils/utils_verify.h +@@ -124,6 +124,8 @@ bool util_valid_sysctl(const char *sysctl_key); + + bool util_valid_volume_name(const char *name); + ++bool util_valid_isulad_tmpdir(const char *dir); ++ + #ifdef ENABLE_IMAGE_SEARCH + bool util_valid_search_name(const char *name); + #endif +diff --git a/src/utils/tar/util_archive.c b/src/utils/tar/util_archive.c +index 82e940a5..e8fad391 100644 +--- a/src/utils/tar/util_archive.c ++++ b/src/utils/tar/util_archive.c +@@ -134,7 +134,7 @@ static void do_disable_unneccessary_caps() + // Add flock when bind mount and make it private. + // Because bind mount usually makes safedir shared mount point, + // and sometimes it will cause "mount point explosion". +-// E.g. concurrently execute isula cp /tmp/ : ++// E.g. concurrently execute isula cp DEFAULT_ISULAD_TMPDIR/ : + static int bind_mount_with_flock(const char *flock_path, const char *dstdir, const char *tmp_dir) + { + __isula_auto_close int fd = -1; +@@ -192,9 +192,10 @@ static int make_safedir_is_noexec(const char *flock_path, const char *dstdir, ch + int nret; + + isulad_tmpdir_env = getenv("ISULAD_TMPDIR"); +- if (!util_valid_str(isulad_tmpdir_env)) { +- // if not setted isulad tmpdir, just use /tmp +- isulad_tmpdir_env = "/tmp"; ++ if (!util_valid_isulad_tmpdir(isulad_tmpdir_env)) { ++ INFO("if not setted isulad tmpdir or setted unvalid dir, use DEFAULT_ISULAD_TMPDIR"); ++ // if not setted isulad tmpdir, just use DEFAULT_ISULAD_TMPDIR ++ isulad_tmpdir_env = DEFAULT_ISULAD_TMPDIR; + } + + nret = snprintf(isula_tmpdir, PATH_MAX, "%s/isulad_tmpdir", isulad_tmpdir_env); +-- +2.42.0 + diff --git a/0053-prevent-the-parent-dir-from-being-bind-mounted-to-th.patch b/0053-prevent-the-parent-dir-from-being-bind-mounted-to-th.patch new file mode 100644 index 0000000..9876957 --- /dev/null +++ b/0053-prevent-the-parent-dir-from-being-bind-mounted-to-th.patch @@ -0,0 +1,58 @@ +From 05117ed2887ee1535978170cd06596ee015951f4 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Tue, 12 Dec 2023 20:26:30 +0800 +Subject: [PATCH 53/64] prevent the parent dir from being bind mounted to the + subdir + +Signed-off-by: zhongtao +--- + src/utils/tar/util_archive.c | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/src/utils/tar/util_archive.c b/src/utils/tar/util_archive.c +index e8fad391..29c2bc03 100644 +--- a/src/utils/tar/util_archive.c ++++ b/src/utils/tar/util_archive.c +@@ -182,6 +182,26 @@ unlock_out: + return ret; + } + ++static int is_parent_directory(const char *parent_path, const char *child_path) ++{ ++ size_t parent_len = strlen(parent_path); ++ size_t child_len = strlen(child_path); ++ ++ if (parent_len == 0 || child_len == 0 || parent_len >= child_len) { ++ return -1; ++ } ++ ++ if (strncmp(parent_path, child_path, parent_len) != 0) { ++ return -1; ++ } ++ ++ if (child_path[parent_len] != '/') { ++ return -1; ++ } ++ ++ return 0; ++} ++ + static int make_safedir_is_noexec(const char *flock_path, const char *dstdir, char **safe_dir) + { + struct stat buf; +@@ -235,6 +255,12 @@ static int make_safedir_is_noexec(const char *flock_path, const char *dstdir, ch + return -1; + } + ++ // prevent the parent directory from being bind mounted to the subdirectory ++ if (is_parent_directory(dstdir, tmp_dir) == 0) { ++ ERROR("Cannot bind mount the parent directory: %s to its subdirectory: %s", dstdir, tmp_dir); ++ return -1; ++ } ++ + if (bind_mount_with_flock(flock_path, dstdir, tmp_dir) != 0) { + ERROR("Failed to bind mount from %s to %s with flock", dstdir, tmp_dir); + if (util_path_remove(tmp_dir) != 0) { +-- +2.42.0 + diff --git a/0054-2308-Remove-unused-header-file.patch b/0054-2308-Remove-unused-header-file.patch new file mode 100644 index 0000000..c783229 --- /dev/null +++ b/0054-2308-Remove-unused-header-file.patch @@ -0,0 +1,25 @@ +From 93071602df77cc3b5508266b181f1ace947bd3be Mon Sep 17 00:00:00 2001 +From: xuxuepeng +Date: Wed, 13 Dec 2023 02:34:20 +0000 +Subject: [PATCH 54/64] !2308 Remove unused header file * Fix compiling failure + in image oci UT + +--- + src/daemon/config/isulad_config.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/daemon/config/isulad_config.c b/src/daemon/config/isulad_config.c +index 1af47127..51758adb 100644 +--- a/src/daemon/config/isulad_config.c ++++ b/src/daemon/config/isulad_config.c +@@ -32,7 +32,6 @@ + + #include "constants.h" + #include "utils.h" +-#include "sysinfo.h" + #include "err_msg.h" + #include "daemon_arguments.h" + #include "utils_array.h" +-- +2.42.0 + diff --git a/0055-verify-the-mount-dir-first-and-then-create-tmpdir.patch b/0055-verify-the-mount-dir-first-and-then-create-tmpdir.patch new file mode 100644 index 0000000..90caa48 --- /dev/null +++ b/0055-verify-the-mount-dir-first-and-then-create-tmpdir.patch @@ -0,0 +1,43 @@ +From 3d38013418d0c5304dfbafcb0b2a5b4062964c53 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Wed, 13 Dec 2023 15:13:12 +0800 +Subject: [PATCH 55/64] verify the mount dir first and then create tmpdir + +Signed-off-by: zhongtao +--- + src/utils/tar/util_archive.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/utils/tar/util_archive.c b/src/utils/tar/util_archive.c +index 29c2bc03..655b3516 100644 +--- a/src/utils/tar/util_archive.c ++++ b/src/utils/tar/util_archive.c +@@ -235,6 +235,12 @@ static int make_safedir_is_noexec(const char *flock_path, const char *dstdir, ch + return -1; + } + ++ // prevent the parent directory from being bind mounted to the subdirectory ++ if (is_parent_directory(dstdir, tmp_dir) == 0) { ++ ERROR("Cannot bind mount the parent directory: %s to its subdirectory: %s", dstdir, tmp_dir); ++ return -1; ++ } ++ + if (stat(dstdir, &buf) < 0) { + SYSERROR("Check chroot dir failed"); + return -1; +@@ -255,12 +261,6 @@ static int make_safedir_is_noexec(const char *flock_path, const char *dstdir, ch + return -1; + } + +- // prevent the parent directory from being bind mounted to the subdirectory +- if (is_parent_directory(dstdir, tmp_dir) == 0) { +- ERROR("Cannot bind mount the parent directory: %s to its subdirectory: %s", dstdir, tmp_dir); +- return -1; +- } +- + if (bind_mount_with_flock(flock_path, dstdir, tmp_dir) != 0) { + ERROR("Failed to bind mount from %s to %s with flock", dstdir, tmp_dir); + if (util_path_remove(tmp_dir) != 0) { +-- +2.42.0 + diff --git a/0056-2300-Maintaining-a-uniform-code-style.patch b/0056-2300-Maintaining-a-uniform-code-style.patch new file mode 100644 index 0000000..f6e434c --- /dev/null +++ b/0056-2300-Maintaining-a-uniform-code-style.patch @@ -0,0 +1,26 @@ +From 2f36e5cae2414804040b6168b79011550281d8d7 Mon Sep 17 00:00:00 2001 +From: chen524 +Date: Wed, 13 Dec 2023 08:02:20 +0000 +Subject: [PATCH 56/64] !2300 Maintaining a uniform code style * update + src/cmd/command_parser.c. + +--- + src/cmd/command_parser.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/cmd/command_parser.c b/src/cmd/command_parser.c +index 1ad1d92b..93b19dae 100644 +--- a/src/cmd/command_parser.c ++++ b/src/cmd/command_parser.c +@@ -438,7 +438,7 @@ int command_valid_socket_append_array(command_option_t *option, const char *arg) + } + + if (util_array_append(option->data, arg) != 0) { +- ERROR("merge hosts config failed"); ++ COMMAND_ERROR("Merge hosts config failed"); + return -1; + } + len++; +-- +2.42.0 + diff --git a/0057-2312-Add-Huawei-Cloud-CodeArts-compilation-script.patch b/0057-2312-Add-Huawei-Cloud-CodeArts-compilation-script.patch new file mode 100644 index 0000000..3845146 --- /dev/null +++ b/0057-2312-Add-Huawei-Cloud-CodeArts-compilation-script.patch @@ -0,0 +1,36 @@ +From 5efff4c61ed885ce45d62e33e2e97a78519fefe8 Mon Sep 17 00:00:00 2001 +From: dreamloy <3038807110@qq.com> +Date: Wed, 13 Dec 2023 08:39:04 +0000 +Subject: [PATCH 57/64] =?UTF-8?q?!2312=20Add=20Huawei=20Cloud=20CodeArts?= + =?UTF-8?q?=20compilation=20script=20*=20=E5=B0=86codecheck=5Fcompile.sh?= + =?UTF-8?q?=20=E7=A7=BB=E5=8A=A8=E5=88=B0tools=E4=B8=8B=20*=20=E6=96=B0?= + =?UTF-8?q?=E5=A2=9E=E5=8D=8E=E4=B8=BA=E4=BA=91codeArs=E7=BC=96=E8=AF=91?= + =?UTF-8?q?=E8=84=9A=E6=9C=AC?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +--- + tools/codecheck_compile.sh | 9 +++++++++ + 1 file changed, 9 insertions(+) + create mode 100644 tools/codecheck_compile.sh + +diff --git a/tools/codecheck_compile.sh b/tools/codecheck_compile.sh +new file mode 100644 +index 00000000..99cadfe7 +--- /dev/null ++++ b/tools/codecheck_compile.sh +@@ -0,0 +1,9 @@ ++## 华为云codeArts执行版本检查时,规则集涉及到代码安全增强包需要编译脚本才能执行 ++BASEPATH=$( cd -- "$( dirname -- "${BASH_SOURCE[0]:-$0}" )" &> /dev/null && pwd ) ++ROOTDIR="$BASEPATH" ++PROGRAM=$(basename "${BASH_SOURCE[0]:-$0}") ++whoami ++ls ++cd docs/build_docs/guide/script ++chmod +x ./install_iSulad_on_Ubuntu_20_04_LTS.sh ++./install_iSulad_on_Ubuntu_20_04_LTS.sh +\ No newline at end of file +-- +2.42.0 + diff --git a/0058-bugfix-del-redundant-code.patch b/0058-bugfix-del-redundant-code.patch new file mode 100644 index 0000000..94072ce --- /dev/null +++ b/0058-bugfix-del-redundant-code.patch @@ -0,0 +1,26 @@ +From a593232e7f34de03142388fddecbea8f3b617245 Mon Sep 17 00:00:00 2001 +From: liuxu +Date: Wed, 13 Dec 2023 17:06:37 +0800 +Subject: [PATCH 58/64] bugfix:del redundant code + +--- + src/daemon/modules/image/image.c | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/src/daemon/modules/image/image.c b/src/daemon/modules/image/image.c +index 4a1950fe..f01265bf 100644 +--- a/src/daemon/modules/image/image.c ++++ b/src/daemon/modules/image/image.c +@@ -602,9 +602,6 @@ void free_im_prepare_request(im_prepare_request *request) + free(request->mount_label); + request->mount_label = NULL; + +- free(request->mount_label); +- request->mount_label = NULL; +- + free_json_map_string_string(request->storage_opt); + request->storage_opt = NULL; + +-- +2.42.0 + diff --git a/0059-improve-code-of-pull.patch b/0059-improve-code-of-pull.patch new file mode 100644 index 0000000..e2c236e --- /dev/null +++ b/0059-improve-code-of-pull.patch @@ -0,0 +1,71 @@ +From e47abc01c8778cc07c11a331ae31ce46b6fd06a0 Mon Sep 17 00:00:00 2001 +From: haozi007 +Date: Thu, 14 Dec 2023 10:59:34 +0800 +Subject: [PATCH 59/64] improve code of pull + +1. ignore unneccessary error log; +2. do not show progress, if stdout is not tty; + +Signed-off-by: haozi007 +--- + src/cmd/isula/images/pull.c | 6 ++++++ + .../modules/image/oci/storage/image_store/image_type.c | 8 ++++++++ + .../layer_store/graphdriver/overlay2/driver_overlay2.c | 5 +++++ + 3 files changed, 19 insertions(+) + +diff --git a/src/cmd/isula/images/pull.c b/src/cmd/isula/images/pull.c +index 9d420778..b30cc0bd 100644 +--- a/src/cmd/isula/images/pull.c ++++ b/src/cmd/isula/images/pull.c +@@ -36,6 +36,12 @@ struct client_arguments g_cmd_pull_args = {}; + static bool is_terminal_show_supported() + { + #ifdef GRPC_CONNECTOR ++ // if stdout is not tty, just ingore progress ++ if (!isatty(STDOUT_FILENO)) { ++ WARN("Stdout is not tty device, just ignore progress."); ++ return false; ++ } ++ + // Initialize the terminfo database + setupterm(NULL, STDOUT_FILENO, (int *)0); + +diff --git a/src/daemon/modules/image/oci/storage/image_store/image_type.c b/src/daemon/modules/image/oci/storage/image_store/image_type.c +index 50af0a69..50a81db2 100644 +--- a/src/daemon/modules/image/oci/storage/image_store/image_type.c ++++ b/src/daemon/modules/image/oci/storage/image_store/image_type.c +@@ -77,6 +77,14 @@ int try_fill_image_spec(image_t *img, const char *id, const char *image_store_di + goto out; + } + ++ // for new_image(), first try will failed because config file not exist ++ // and image_store_set_big_data() will retry this function ++ if (!util_file_exists(config_file)) { ++ WARN("Oci image spec: %s not found.", config_file); ++ ret = -1; ++ goto out; ++ } ++ + img->spec = oci_image_spec_parse_file(config_file, NULL, &err); + if (img->spec == NULL) { + ERROR("Failed to parse oci image spec: %s", err); +diff --git a/src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2/driver_overlay2.c b/src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2/driver_overlay2.c +index 3bc433ae..3d814954 100644 +--- a/src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2/driver_overlay2.c ++++ b/src/daemon/modules/image/oci/storage/layer_store/graphdriver/overlay2/driver_overlay2.c +@@ -1133,7 +1133,12 @@ static char *read_layer_lower_file(const char *layer_dir) + goto out; + } + ++ // lowest layer do not have lower file ++ if (!util_file_exists(lower_file)) { ++ goto out; ++ } + lower = util_read_text_file(lower_file); ++ + out: + free(lower_file); + return lower; +-- +2.42.0 + diff --git a/0060-remove-var-in-coverage-and-fix-build-test-remove.patch b/0060-remove-var-in-coverage-and-fix-build-test-remove.patch new file mode 100644 index 0000000..3c1de53 --- /dev/null +++ b/0060-remove-var-in-coverage-and-fix-build-test-remove.patch @@ -0,0 +1,30 @@ +From f1fa4c7bdc2c67a4ef9c476ba9e0e2de6b589bc5 Mon Sep 17 00:00:00 2001 +From: jikai +Date: Thu, 14 Dec 2023 10:49:26 +0800 +Subject: [PATCH 60/64] remove /var/* in coverage and fix build/test remove + +Signed-off-by: jikai +--- + CI/generate_gcov.sh | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/CI/generate_gcov.sh b/CI/generate_gcov.sh +index 76bf382b..7518c5c1 100755 +--- a/CI/generate_gcov.sh ++++ b/CI/generate_gcov.sh +@@ -29,10 +29,8 @@ cp -r ~/build $ISULAD_COPY_PATH + cd $ISULAD_COPY_PATH/build + ctest + lcov --directory . --capture --output-file coverage.info --rc lcov_branch_coverage=1 +-# Remove std/build files +-lcov --remove coverage.info '/usr/*' -o coverage.info --rc lcov_branch_coverage=1 +-lcov --remove coverage.info "$ISULAD_SRC_PATH/build/*" -o coverage.info --rc lcov_branch_coverage=1 +-lcov --remove coverage.info "$ISULAD_SRC_PATH/test/*" -o coverage.info --rc lcov_branch_coverage=1 ++# extract src only files ++lcov --extract coverage.info '*/iSulad/src/*' -o coverage.info --rc lcov_branch_coverage=1 + + # Generate html + genhtml --ignore-errors source -o $GCOV_RESULT_PATH/coverage coverage.info --branch-coverage --rc lcov_branch_coverage=1 +-- +2.42.0 + diff --git a/0061-2320-improve-CI-test.patch b/0061-2320-improve-CI-test.patch new file mode 100644 index 0000000..1c7326c --- /dev/null +++ b/0061-2320-improve-CI-test.patch @@ -0,0 +1,165 @@ +From 712d82656ac9bafda7d29be70e7dbcd761a01f98 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Sun, 17 Dec 2023 05:58:56 +0000 +Subject: [PATCH 61/64] !2320 improve CI test * improve CI test + +--- + .../container_cases/restartpolicy.sh | 35 ++++++++++++++----- + CI/test_cases/image_cases/image_digest.sh | 10 +++--- + CI/test_cases/image_cases/image_search.sh | 26 ++------------ + 3 files changed, 35 insertions(+), 36 deletions(-) + +diff --git a/CI/test_cases/container_cases/restartpolicy.sh b/CI/test_cases/container_cases/restartpolicy.sh +index 11c3608f..0ab09636 100755 +--- a/CI/test_cases/container_cases/restartpolicy.sh ++++ b/CI/test_cases/container_cases/restartpolicy.sh +@@ -23,18 +23,37 @@ curr_path=$(dirname $(readlink -f "$0")) + data_path=$(realpath $curr_path/../data) + source ../helpers.sh + ++# $1 : retry limit ++# $2 : retry_interval ++# $3 : container name ++# $4 : expect restart count ++function do_retry() ++{ ++ for i in $(seq 1 "$1"); do ++ count=`isula inspect --format='{{json .RestartCount}}' ${3}` ++ if [ $count -eq $4 ]; then ++ return 0 ++ fi ++ sleep $2 ++ done ++ echo "expect $4, get $count" ++ return 1 ++} ++ + function do_test_on_failure() + { ++ local retry_limit=15 ++ local retry_interval=1 + containername=test_rp_on_failure + isula run --name $containername -td --restart on-failure:3 busybox /bin/sh -c "exit 2" + fn_check_eq "$?" "0" "run failed" + +- sleep 8 +- count=`isula inspect --format='{{json .RestartCount}}' $containername` +- if [[ $count != "3" ]];then +- echo "expect 3 but get $count" ++ do_retry ${retry_limit} ${retry_interval} ${containername} 3 ++ if [[ $? -ne 0 ]];then + TC_RET_T=$(($TC_RET_T+1)) + fi ++ ++ isula stop -t 0 $containername + testcontainer $containername exited + + isula rm $containername +@@ -43,14 +62,14 @@ function do_test_on_failure() + + function do_test_unless_stopped() + { ++ local retry_limit=15 ++ local retry_interval=1 + containername=test_rp_unless_stopped + isula run --name $containername -td --restart unless-stopped busybox /bin/sh -c "exit 2" + fn_check_eq "$?" "0" "run failed" + +- sleep 8 +- count=`isula inspect --format='{{json .RestartCount}}' $containername` +- if [[ $count == "0" ]];then +- echo "expect not 0 but get $count" ++ do_retry ${retry_limit} ${retry_interval} ${containername} 0 ++ if [[ $? -ne 0 ]];then + TC_RET_T=$(($TC_RET_T+1)) + fi + +diff --git a/CI/test_cases/image_cases/image_digest.sh b/CI/test_cases/image_cases/image_digest.sh +index e30f29f0..cc8b0e48 100755 +--- a/CI/test_cases/image_cases/image_digest.sh ++++ b/CI/test_cases/image_cases/image_digest.sh +@@ -25,14 +25,14 @@ source ../helpers.sh + function test_image_with_digest() + { + local ret=0 +- local image="busybox" +- local image2="ubuntu" +- local image_digest="busybox@sha256:5cd3db04b8be5773388576a83177aff4f40a03457a63855f4b9cbe30542b9a43" ++ local image="3laho3y3.mirror.aliyuncs.com/library/busybox" ++ local image2="3laho3y3.mirror.aliyuncs.com/library/ubuntu" ++ local image_digest="3laho3y3.mirror.aliyuncs.com/library/busybox@sha256:62ffc2ed7554e4c6d360bce40bbcf196573dd27c4ce080641a2c59867e732dee" + local test="pull && inspect && tag image with digest test => (${FUNCNAME[@]})" + + msg_info "${test} starting..." + +- isula pull docker.io/library/${image_digest} ++ isula pull ${image_digest} + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to pull image: ${image}" && return ${FAILURE} + + isula tag ${image_digest} ${image}:digest_test +@@ -71,7 +71,7 @@ function test_image_with_digest() + isula inspect -f '{{.image.repo_tags}}' ${image_digest} | grep "${image}:digest_test" + [[ $? -eq 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - image digest delete error: ${image_digest}" && ((ret++)) + +- isula pull docker.io/library/${image2}:latest ++ isula pull ${image2}:latest + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to pull image: ${image2}" && return ${FAILURE} + + digest=$(isula inspect "${image2}:latest" | grep "@sha256" | awk -F"\"" '{print $2}') +diff --git a/CI/test_cases/image_cases/image_search.sh b/CI/test_cases/image_cases/image_search.sh +index 1d281cb2..11af02f1 100755 +--- a/CI/test_cases/image_cases/image_search.sh ++++ b/CI/test_cases/image_cases/image_search.sh +@@ -33,6 +33,7 @@ function test_image_search() + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - stop isulad failed" && return ${FAILURE} + + msg_info "${test} starting..." ++ rm -rf /etc/isulad/daemon.bak + cp /etc/isulad/daemon.json /etc/isulad/daemon.bak + sed -i "/registry-mirrors/a\ \"docker.io\"," /etc/isulad/daemon.json + +@@ -49,39 +50,18 @@ function test_image_search() + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - search ${invalid_image} should fail as it's search name is invalid" && return ${FAILURE} + + # test search options +- isula search --no-trunc ${image} +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to search images with no-trunc: ${image}" && ((ret++)) +- +- isula search --limit 5 ${image} +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to search images with limit: ${image}" && ((ret++)) ++ isula search --no-trunc --limit 5 --filter stars=3 --filter is-official=true --filter is-automated=false --format "table {{.Name}}\t{{.IsOfficial}}" ${image} ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to search images with search options: ${image}" && ((ret++)) + + isula search --limit -1 ${image} 2>&1 | grep "Invalid value" + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to search images with limit: ${image} and and catch error msg" && ((ret++)) + +- isula search --filter stars=3 ${image} +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to search images with filter stars: ${image}" && ((ret++)) +- +- isula search --filter is-official=true ${image} +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to search images with filter is-official: ${image}" && ((ret++)) +- +- isula search --filter is-automated=true ${image} 2>&1 | grep "AUTOMATED" +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to search images with filter is-automated: ${image}" && ((ret++)) +- + isula search --filter aa=true ${image} 2>&1 | grep "Invalid filter" + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to set filter for search ${image} and catch error msg" && ((ret++)) + +- isula search ${image} 2>&1 | grep "NAME" +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to search images with default table format: ${image}" && ((ret++)) +- +- isula search --format "table {{.IsAutomated}}\t{{.IsOfficial}}" ${image} 2>&1 | grep "AUTOMATED" +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to search images with table format: ${image}" && ((ret++)) +- + isula search --format "{{Name}}" ${image} 2>&1 | grep "invalid format field" + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to set format for search ${image} and catch error msg" && ((ret++)) + +- isula search --format "{{.Name}}" ${image} 2>&1 +- [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to search images with none-table format: ${image}" && ((ret++)) +- + cp -f /etc/isulad/daemon.bak /etc/isulad/daemon.json + + check_valgrind_log +-- +2.42.0 + diff --git a/0062-verify-name-and-digest-consistency.patch b/0062-verify-name-and-digest-consistency.patch new file mode 100644 index 0000000..e56bbd7 --- /dev/null +++ b/0062-verify-name-and-digest-consistency.patch @@ -0,0 +1,319 @@ +From 950dc3c56f192061383de4d19229ace243eae503 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Mon, 18 Dec 2023 15:54:37 +0800 +Subject: [PATCH 62/64] verify name and digest consistency + +Signed-off-by: zhongtao +--- + .../oci/storage/image_store/image_store.c | 265 +++++++++++------- + 1 file changed, 162 insertions(+), 103 deletions(-) + +diff --git a/src/daemon/modules/image/oci/storage/image_store/image_store.c b/src/daemon/modules/image/oci/storage/image_store/image_store.c +index 58baa47a..1b482504 100644 +--- a/src/daemon/modules/image/oci/storage/image_store/image_store.c ++++ b/src/daemon/modules/image/oci/storage/image_store/image_store.c +@@ -22,6 +22,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -444,11 +445,161 @@ out: + return value; + } + ++static int resort_image_names(const char **names, size_t names_len, char **first_name, char ***image_tags, ++ char ***image_digests) ++{ ++ int ret = 0; ++ size_t i; ++ char *prefix = NULL; ++ ++ for (i = 0; i < names_len; i++) { ++ size_t len = strlen(names[i]); ++ if (strlen(names[i]) > MAX_IMAGE_NAME_LENGTH) { ++ prefix = util_sub_string(names[i], len - MAX_IMAGE_NAME_LENGTH, ++ MAX_IMAGE_NAME_LENGTH - MAX_IMAGE_DIGEST_LENGTH); ++ } ++ ++ // TODO: maybe should support other digest ++ if (prefix != NULL && strcmp(prefix, DIGEST_PREFIX) == 0) { ++ if (util_array_append(image_digests, names[i]) != 0) { ++ ERROR("Failed to append image to digest: %s", names[i]); ++ ret = -1; ++ goto out; ++ } ++ } else { ++ if (util_array_append(image_tags, names[i]) != 0) { ++ ERROR("Failed to append image to tags: %s", names[i]); ++ ret = -1; ++ goto out; ++ } ++ } ++ } ++ ++ if (first_name == NULL) { ++ goto out; ++ } ++ ++ if (util_array_len((const char **)(*image_digests)) > 0) { ++ free(*first_name); ++ *first_name = util_strdup_s((*image_digests)[0]); ++ } ++ ++ if (util_array_len((const char **)(*image_tags)) > 0) { ++ free(*first_name); ++ *first_name = util_strdup_s((*image_tags)[0]); ++ } ++ ++out: ++ if (ret != 0) { ++ util_free_array(*image_digests); ++ util_free_array(*image_tags); ++ free(*first_name); ++ } ++ free(prefix); ++ return ret; ++} ++ ++// Validate checks that the contents is a valid digest ++static bool validate_digest(const char *digest) ++{ ++ bool ret = true; ++ const char *sha256_encode_patten = "^[a-f0-9]{64}$"; ++ char *value = util_strdup_s(digest); ++ char *index = strchr(value, ':'); ++ char *alg = NULL; ++ char *encode = NULL; ++ ++ // contains ':' and is not the last character ++ if (index == NULL || index - value + 1 == strlen(value)) { ++ INFO("Invalid checksum digest format"); ++ ret = false; ++ goto out; ++ } ++ ++ *index++ = '\0'; ++ ++ alg = value; ++ encode = index; ++ // Currently only support SHA256 algorithm ++ if (strcmp(alg, "sha256") != 0) { ++ DEBUG("Unsupported digest algorithm: %s", alg); ++ ret = false; ++ goto out; ++ } ++ ++ ret = util_reg_match(sha256_encode_patten, encode) == 0; ++ ++out: ++ free(value); ++ return ret; ++} ++ ++// Parsing a reference string as a possible identifier, full digest, or familiar name. ++static char *parse_digest_reference(const char *ref) ++{ ++ char *indentfier_patten = "^[a-f0-9]{64}$"; ++ ++ if (util_reg_match(indentfier_patten, ref) == 0) { ++ return util_string_append(ref, "sha256:"); ++ } ++ ++ if (validate_digest(ref)) { ++ return util_strdup_s(ref); ++ } ++ ++ return oci_normalize_image_name(ref); ++} ++ ++static int is_name_digest_consistent(const char *name, char **names, size_t names_len, const char *digest) ++{ ++ size_t i; ++ int ret = -1; ++ int nret = 0; ++ char *tag_pos = NULL; ++ char **tags = NULL; ++ char **digests = NULL; ++ ++ if (resort_image_names((const char **)names, names_len, NULL, &tags, &digests) != 0) { ++ ERROR("Failed to resort image names"); ++ goto out; ++ } ++ ++ for (i = 0; i < util_array_len((const char **)tags); i++) { ++ __isula_auto_free char *ref = NULL; ++ __isula_auto_free char *tmp_repo_digests = NULL; ++ ref = parse_digest_reference(tags[i]); ++ if (ref == NULL) { ++ continue; ++ } ++ tag_pos = util_tag_pos(ref); ++ if (tag_pos == NULL) { ++ ERROR("invalid ref %s", ref); ++ continue; ++ } ++ *tag_pos = '\0'; ++ ++ nret = asprintf(&tmp_repo_digests, "%s@%s", ref, digest); ++ if (nret < 0) { ++ ERROR("Failed to receive repo digest"); ++ goto out; ++ } ++ if (strcmp(name, tmp_repo_digests) == 0) { ++ ret = 0; ++ goto out; ++ } ++ } ++out: ++ util_free_array(tags); ++ util_free_array(digests); ++ return ret; ++} ++ + // by_digest returns the image which matches the specified name. + static image_t *by_digest(const char *name) + { + digest_image_t *digest_filter_images = NULL; + char *digest = NULL; ++ image_t *tmp_ret = NULL; + + // split digest for image name with digest + digest = strrchr(name, '@'); +@@ -457,12 +608,21 @@ static image_t *by_digest(const char *name) + } + digest++; + digest_filter_images = (digest_image_t *)map_search(g_image_store->bydigest, (void *)digest); +- if (digest_filter_images == NULL) { ++ if (digest_filter_images == NULL || linked_list_empty(&(digest_filter_images->images_list))) { + return NULL; + } + + // currently, a digest corresponds to an image, directly returning the first element +- return linked_list_first_elem(&(digest_filter_images->images_list)); ++ tmp_ret = linked_list_first_elem(&(digest_filter_images->images_list)); ++ ++ // verify name and digest consistency to ensure we are not matching images to different repositories, ++ // even if the digests match. ++ // For example, ubuntu@sha256:abc......, shouldn't match test@sha256:abc...... ++ if (is_name_digest_consistent(name, tmp_ret->simage->names, tmp_ret->simage->names_len, digest) != 0) { ++ return NULL; ++ } ++ ++ return tmp_ret; + } + + static image_t *lookup(const char *id) +@@ -2001,107 +2161,6 @@ out: + return ret; + } + +-static int resort_image_names(const char **names, size_t names_len, char **first_name, char ***image_tags, +- char ***image_digests) +-{ +- int ret = 0; +- size_t i; +- char *prefix = NULL; +- +- for (i = 0; i < names_len; i++) { +- size_t len = strlen(names[i]); +- if (strlen(names[i]) > MAX_IMAGE_NAME_LENGTH) { +- prefix = util_sub_string(names[i], len - MAX_IMAGE_NAME_LENGTH, +- MAX_IMAGE_NAME_LENGTH - MAX_IMAGE_DIGEST_LENGTH); +- } +- +- // TODO: maybe should support other digest +- if (prefix != NULL && strcmp(prefix, DIGEST_PREFIX) == 0) { +- if (util_array_append(image_digests, names[i]) != 0) { +- ERROR("Failed to append image to digest: %s", names[i]); +- ret = -1; +- goto out; +- } +- } else { +- if (util_array_append(image_tags, names[i]) != 0) { +- ERROR("Failed to append image to tags: %s", names[i]); +- ret = -1; +- goto out; +- } +- } +- } +- +- if (util_array_len((const char **)(*image_digests)) > 0) { +- free(*first_name); +- *first_name = util_strdup_s((*image_digests)[0]); +- } +- +- if (util_array_len((const char **)(*image_tags)) > 0) { +- free(*first_name); +- *first_name = util_strdup_s((*image_tags)[0]); +- } +- +-out: +- if (ret != 0) { +- util_free_array(*image_digests); +- util_free_array(*image_tags); +- free(*first_name); +- } +- free(prefix); +- return ret; +-} +- +-// Validate checks that the contents is a valid digest +-static bool validate_digest(const char *digest) +-{ +- bool ret = true; +- const char *sha256_encode_patten = "^[a-f0-9]{64}$"; +- char *value = util_strdup_s(digest); +- char *index = strchr(value, ':'); +- char *alg = NULL; +- char *encode = NULL; +- +- // contains ':' and is not the last character +- if (index == NULL || index - value + 1 == strlen(value)) { +- INFO("Invalid checksum digest format"); +- ret = false; +- goto out; +- } +- +- *index++ = '\0'; +- +- alg = value; +- encode = index; +- // Currently only support SHA256 algorithm +- if (strcmp(alg, "sha256") != 0) { +- DEBUG("Unsupported digest algorithm: %s", alg); +- ret = false; +- goto out; +- } +- +- ret = util_reg_match(sha256_encode_patten, encode) == 0; +- +-out: +- free(value); +- return ret; +-} +- +-// Parsing a reference string as a possible identifier, full digest, or familiar name. +-static char *parse_digest_reference(const char *ref) +-{ +- char *indentfier_patten = "^[a-f0-9]{64}$"; +- +- if (util_reg_match(indentfier_patten, ref) == 0) { +- return util_string_append(ref, "sha256:"); +- } +- +- if (validate_digest(ref)) { +- return util_strdup_s(ref); +- } +- +- return oci_normalize_image_name(ref); +-} +- + static int pack_repo_digest(char ***old_repo_digests, const char **image_tags, const char *digest, char ***repo_digests) + { + int ret = 0; +-- +2.42.0 + diff --git a/0063-code-improve-for-oci_rmi.patch b/0063-code-improve-for-oci_rmi.patch new file mode 100644 index 0000000..0d8f427 --- /dev/null +++ b/0063-code-improve-for-oci_rmi.patch @@ -0,0 +1,35 @@ +From 2db6add74c621344e902ce28b5e6764f6ef55b8e Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Mon, 18 Dec 2023 16:07:57 +0800 +Subject: [PATCH 63/64] code improve for oci_rmi + +Signed-off-by: zhongtao +--- + src/daemon/modules/image/oci/oci_image.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/src/daemon/modules/image/oci/oci_image.c b/src/daemon/modules/image/oci/oci_image.c +index 471510e7..9cf2cd4f 100644 +--- a/src/daemon/modules/image/oci/oci_image.c ++++ b/src/daemon/modules/image/oci/oci_image.c +@@ -542,6 +542,17 @@ int oci_rmi(const im_rmi_request *request) + goto out; + } + ++ for (i = 0; i < image_names_len; i++) { ++ if (strcmp(real_image_name, image_names[i]) == 0) { ++ break; ++ } ++ } ++ if (i == image_names_len) { ++ ERROR("Invalid real_image_name"); ++ ret = -1; ++ goto out; ++ } ++ + reduced_image_names = (char **)util_smart_calloc_s(sizeof(char *), image_names_len - 1); + if (reduced_image_names == NULL) { + ERROR("Out of memory"); +-- +2.42.0 + diff --git a/0064-bugfix-for-resort_image_names.patch b/0064-bugfix-for-resort_image_names.patch new file mode 100644 index 0000000..19ef9cb --- /dev/null +++ b/0064-bugfix-for-resort_image_names.patch @@ -0,0 +1,26 @@ +From 39686ee4443400b810edecb38e3891b808e3a065 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Mon, 18 Dec 2023 20:59:46 +0800 +Subject: [PATCH 64/64] bugfix for resort_image_names + +Signed-off-by: zhongtao +--- + src/daemon/modules/image/oci/storage/image_store/image_store.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/daemon/modules/image/oci/storage/image_store/image_store.c b/src/daemon/modules/image/oci/storage/image_store/image_store.c +index 1b482504..034268bc 100644 +--- a/src/daemon/modules/image/oci/storage/image_store/image_store.c ++++ b/src/daemon/modules/image/oci/storage/image_store/image_store.c +@@ -473,6 +473,8 @@ static int resort_image_names(const char **names, size_t names_len, char **first + goto out; + } + } ++ free(prefix); ++ prefix = NULL; + } + + if (first_name == NULL) { +-- +2.42.0 + diff --git a/0065-fix-stopp-removes-cont-error-remove-inspect-error-lo.patch b/0065-fix-stopp-removes-cont-error-remove-inspect-error-lo.patch new file mode 100644 index 0000000..ba38cc7 --- /dev/null +++ b/0065-fix-stopp-removes-cont-error-remove-inspect-error-lo.patch @@ -0,0 +1,76 @@ +From 3d8c6127161acbe35bf03fe495ac43e2b9242cbf Mon Sep 17 00:00:00 2001 +From: jikai +Date: Tue, 19 Dec 2023 18:31:30 +0800 +Subject: [PATCH 65/71] fix stopp removes cont error & remove inspect error log + +Signed-off-by: jikai +--- + .../cri_pod_sandbox_manager_service.cc | 36 ++++++++----------- + .../container_cb/execution_information.c | 2 +- + 2 files changed, 15 insertions(+), 23 deletions(-) + +diff --git a/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc b/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc +index bc40cb06..4d1d19eb 100644 +--- a/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc ++++ b/src/daemon/entry/cri/v1alpha/cri_pod_sandbox_manager_service.cc +@@ -703,30 +703,22 @@ auto PodSandboxManagerService::GetRealSandboxIDToStop(const std::string &podSand + std::map &stdAnnos, Errors &error) + -> int + { +- Errors statusErr; ++ auto status = PodSandboxStatus(podSandboxID, error); ++ if (error.NotEmpty()) { ++ return -1; ++ } + +- auto status = PodSandboxStatus(podSandboxID, statusErr); +- if (statusErr.Empty()) { +- if (status->linux().namespaces().has_options()) { +- hostNetwork = (status->linux().namespaces().options().network() == runtime::v1alpha2::NamespaceMode::NODE); +- } +- // if metadata is invalid, don't return -1 and continue stopping pod +- if (status->has_metadata()) { +- name = status->metadata().name(); +- ns = status->metadata().namespace_(); +- } +- realSandboxID = status->id(); +- CRIHelpers::ProtobufAnnoMapToStd(status->annotations(), stdAnnos); +- } else { +- if (CRIHelpers::IsContainerNotFoundError(statusErr.GetMessage())) { +- WARN("Both sandbox container and checkpoint for id %s could not be found. " +- "Proceed without further sandbox information.", +- podSandboxID.c_str()); +- } else { +- error.Errorf("failed to get sandbox status: %s", statusErr.GetCMessage()); +- return -1; +- } ++ if (status->linux().namespaces().has_options()) { ++ hostNetwork = (status->linux().namespaces().options().network() == runtime::v1alpha2::NamespaceMode::NODE); + } ++ // if metadata is invalid, don't return -1 and continue stopping pod ++ if (status->has_metadata()) { ++ name = status->metadata().name(); ++ ns = status->metadata().namespace_(); ++ } ++ realSandboxID = status->id(); ++ CRIHelpers::ProtobufAnnoMapToStd(status->annotations(), stdAnnos); ++ + if (realSandboxID.empty()) { + realSandboxID = podSandboxID; + } +diff --git a/src/daemon/executor/container_cb/execution_information.c b/src/daemon/executor/container_cb/execution_information.c +index 420f08df..03fce848 100644 +--- a/src/daemon/executor/container_cb/execution_information.c ++++ b/src/daemon/executor/container_cb/execution_information.c +@@ -914,7 +914,7 @@ static int inspect_container_helper(const char *id, int timeout, char **containe + + inspect = inspect_container(id, timeout, true); + if (inspect == NULL) { +- ERROR("Failed to inspect container:%s", id); ++ DEBUG("Failed to inspect container:%s", id); + ret = -1; + goto out; + } +-- +2.25.1 + diff --git a/0066-2313-use-lxc-5.X-in-CI-testcase.patch b/0066-2313-use-lxc-5.X-in-CI-testcase.patch new file mode 100644 index 0000000..a730c39 --- /dev/null +++ b/0066-2313-use-lxc-5.X-in-CI-testcase.patch @@ -0,0 +1,41 @@ +From 1c28f9259463433a7aac10733be09f8d47ec17a5 Mon Sep 17 00:00:00 2001 +From: zhangxiaoyu +Date: Thu, 21 Dec 2023 12:36:52 +0000 +Subject: [PATCH 66/71] !2313 use lxc 5.X in CI testcase * use lxc 5.X in CI + testcase + +--- + CI/install_depends.sh | 16 +++++----------- + 1 file changed, 5 insertions(+), 11 deletions(-) + +diff --git a/CI/install_depends.sh b/CI/install_depends.sh +index 5a4d71fa..ebeb79db 100755 +--- a/CI/install_depends.sh ++++ b/CI/install_depends.sh +@@ -105,18 +105,12 @@ cd ~ + git clone https://gitee.com/src-openeuler/lxc.git + git config --global --add safe.directory ~/lxc/lxc-5.0.2 + cd lxc +-git checkout origin/openEuler-22.03-LTS-SP1 +-tar xf lxc-4.0.3.tar.gz +-cd lxc-4.0.3 +-mv ../*.patch . +-for var in $(ls 0*.patch | sort -n) +-do +- patch -p1 < ${var} +-done ++./apply-patches ++cd lxc-5.0.2 ++mkdir -p build + sed -i 's/fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO/fd == 0 || fd == 1 || fd == 2 || fd >= 1000/g' ./src/lxc/start.c +-./autogen.sh +-./configure --prefix=${builddir} enable_werror=no +-make -j $(nproc) ++meson setup -Disulad=true -Dprefix=${builddir} build ++meson compile -C build + make install + ldconfig + +-- +2.25.1 + diff --git a/0067-2329-modify-mount-dev-directory-for-lxc-5.X.patch b/0067-2329-modify-mount-dev-directory-for-lxc-5.X.patch new file mode 100644 index 0000000..a67684f --- /dev/null +++ b/0067-2329-modify-mount-dev-directory-for-lxc-5.X.patch @@ -0,0 +1,27 @@ +From 4a3ec85d707db28f10d4cd5654abf227dfc515cc Mon Sep 17 00:00:00 2001 +From: zhangxiaoyu +Date: Mon, 25 Dec 2023 09:34:28 +0000 +Subject: [PATCH 67/71] !2329 modify mount /dev directory for lxc 5.X * modify + mount /dev directory for lxc 5.X + +--- + CI/test_cases/container_cases/bind_special_dir.sh | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/CI/test_cases/container_cases/bind_special_dir.sh b/CI/test_cases/container_cases/bind_special_dir.sh +index d030bb08..545d5099 100755 +--- a/CI/test_cases/container_cases/bind_special_dir.sh ++++ b/CI/test_cases/container_cases/bind_special_dir.sh +@@ -42,7 +42,8 @@ function test_bind_special_dir() + if [ $runtime == "runc" ]; then + c_id=`isula run -itd -v -itd --runtime=$runtime -v /sys/fs:/sys/fs:rw -v /proc:/proc -v /dev/pts:/dev/pts:rw busybox sh` + else +- c_id=`isula run --runtime=$runtime -itd -v -itd -v /sys/fs:/sys/fs:rw -v /proc:/proc -v /dev:/dev:ro -v /dev/pts:/dev/pts:rw busybox sh` ++ # lxc 5.X cannot support mount /dev directory ++ c_id=`isula run --runtime=$runtime -itd -v -itd -v /sys/fs:/sys/fs:rw -v /proc:/proc busybox sh` + fi + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - failed to run container with image: ${image}" && ((ret++)) + +-- +2.25.1 + diff --git a/0068-add-cri-1.29-api-change-docs.patch b/0068-add-cri-1.29-api-change-docs.patch new file mode 100644 index 0000000..97aee02 --- /dev/null +++ b/0068-add-cri-1.29-api-change-docs.patch @@ -0,0 +1,139 @@ +From 6ffd8232929b3cd1873c899d6bf379013959fb28 Mon Sep 17 00:00:00 2001 +From: jikai +Date: Fri, 22 Dec 2023 15:26:48 +0800 +Subject: [PATCH 68/71] add cri 1.29 api change docs + +Signed-off-by: jikai +--- + .../detailed/CRI/CRI_1.29_interface_change.md | 105 ++++++++++++++++++ + docs/images/cri_1.29_interface_change.svg | 5 + + 2 files changed, 110 insertions(+) + create mode 100644 docs/design/detailed/CRI/CRI_1.29_interface_change.md + create mode 100644 docs/images/cri_1.29_interface_change.svg + +diff --git a/docs/design/detailed/CRI/CRI_1.29_interface_change.md b/docs/design/detailed/CRI/CRI_1.29_interface_change.md +new file mode 100644 +index 00000000..f94d001b +--- /dev/null ++++ b/docs/design/detailed/CRI/CRI_1.29_interface_change.md +@@ -0,0 +1,105 @@ ++| Author | 吉凯 | ++| ------ | ------------------------ | ++| Date | 2023-12-22 | ++| Email | jikai11@huawei.com | ++ ++### 参考代码 ++ ++升级版本:1.29 ++参考地址: ++ ++### 变更依赖图 ++ ++![](../../../images/cri_1.29_interface_change.svg) ++ ++### 变更说明 ++ ++##### [CRI: Add Windows Podsandbox Stats](https://github.com/kubernetes/kubernetes/pull/110754) ++ ++不支持,无需变更 ++ ++- Added fields to the type `WindowsPodSandboxStats` expressing stats required to be collected from windows pods. ++ ++##### [Windows hostnetwork alpha](https://github.com/kubernetes/kubernetes/pull/112961) ++ ++不支持,无需变更 ++ ++- New type `WindowsNamespaceOption` introduced ++- The type `WindowsSandboxSecurityContext` has a new field `namespace_options` of type `WindowsNamespaceOption` ++ ++##### [Improve the API description of `PodSecurityContext.SupplementalGroups` to clarify its unfamiliar behavior](https://github.com/kubernetes/kubernetes/pull/113047) ++ ++描述修改,优化`PodSecurityContext.SupplementalGroups`的注释,明确容器镜像定义的主UID不在该列表下的行为 ++ ++- Clarified the expected behavior of `SupplementalGroups` field of `PodSecurityContext` ++ ++##### [Add Support for Evented PLEG](https://github.com/kubernetes/kubernetes/pull/111384) ++ ++新增字段,`GetContainerEvent`提供pod status和container status信息,`PodSandboxStatus`提供container status信息,[KEP-3386](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3386-kubelet-evented-pleg/README.md) ++ ++- The type `ContainerEventResponse` updated: the field `pod_sandbox_metadata` removed and fields `pod_sandbox_status` and `containers_statuses` added. ++- The type `PodSandboxStatusResponse` has a new fields `containers_statuses` and `timestamp` ++ ++##### [CRI: Add CDI device info for containers](https://github.com/kubernetes/kubernetes/pull/115891/) ++ ++新增字段,CDI特性支持,CDI设备信息不再从annotation获取,直接从`ContainerConfig`获取,[KEP-3063](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/3063-dynamic-resource-allocation/README.md) ++ ++- New type `CDIDevice` was introduced and added to container config ++ ++##### [Add mappings for volumes](https://github.com/kubernetes/kubernetes/pull/116377) ++ ++新增字段,`Mount`中新增UID/GID映射信息,要求CRI创建挂载绑定时指定UID/GID映射信息,Kubelet不再负责映射, ++[KEP-127](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/127-user-namespaces) ++ ++- Added new fields to the type `Mount` expressing runtime UID/GID mappings for the mount. ++ ++##### [cri-api: fix comment lines about PROPAGATION_PRIVATE](https://github.com/kubernetes/kubernetes/pull/115704) ++ ++描述修改,修改对PROPAGATION_PRIVATE的不正确注释 ++ ++- Fixed comment lines about PROPAGATION_PRIVATE ++ ++##### [Add user specified image to CRI ContainerConfig](https://github.com/kubernetes/kubernetes/pull/118652) ++ ++新增字段,`ImageSpec`新增`user_specified_image`,确保创建容器时验证正确的镜像 ++ ++- Added the `user_specified_image` field to type `ImageSpec` ++ ++##### [kubelet: get cgroup driver config from CRI](https://github.com/kubernetes/kubernetes/pull/118770) ++ ++新增rpc,获取cgroup驱动配置,[KEP-4033](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/4033-group-driver-detection-over-cri) ++ ++- Added rpc for querying runtime configuration ++- Added cavieats about cgroup driver field ++ ++##### [Add swap to stats to Summary API and Prometheus endpoints (/stats/summary and /metrics/resource)](https://github.com/kubernetes/kubernetes/pull/118865) ++ ++新增字段,`ContainerStats`中新增虚拟内存使用情况信息,[KEP-2400](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/2400-node-swap/README.md#beta-1) ++ ++- Added `SwapUsage` type ++- Added `SwapUsage` field to `ContainerStats` type ++ ++##### [Expose commit memory used in WindowsMemoryUsage struct](https://github.com/kubernetes/kubernetes/pull/119238) ++ ++不支持,无需变更。 ++ ++- Added the `commit_memory_bytes` field to type `WindowsMemoryUsage` ++ ++##### [Add runtime handler field to ImageSpec struct](https://github.com/kubernetes/kubernetes/pull/121121) ++ ++新增字段,指定拉取镜像所采用的运行时处理,[KEP-4216](https://github.com/kubernetes/enhancements/tree/master/keps/sig-node/4216-image-pull-per-runtime-class) ++ ++- Added `runtime_handler` field to type `ImageSpec` ++ ++##### [kubelet: add support for broadcasting metrics from CRI](https://github.com/kubernetes/kubernetes/pull/113609) ++ ++新增rpc,`ListMetricDescriptors`和`ListPodSandboxMetrics`获取metrics信息,[KEP-2371](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/2371-cri-pod-container-stats/README.md) ++ ++- Added rpc for pulling the metrics from CRI and broadcasting them to prometheus ++- Added cavieats about metrics ++ ++##### [Kubelet disk api cri update](https://github.com/kubernetes/kubernetes/pull/120914) ++ ++新增字段,`ImageFsInfo`返回值添加容器文件系统信息,[KEP-4191](https://github.com/kubernetes/enhancements/blob/master/keps/sig-node/4191-split-image-filesystem/README.md) ++ ++- Added `container_filesystems` field to type `ImageFsInfoResponse` +diff --git a/docs/images/cri_1.29_interface_change.svg b/docs/images/cri_1.29_interface_change.svg +new file mode 100644 +index 00000000..06026d6f +--- /dev/null ++++ b/docs/images/cri_1.29_interface_change.svg +@@ -0,0 +1,5 @@ ++ ++ ++ ++ ++ ListPodSandboxStatsPodSandboxStatsPodSandboxStatsWindowsPodSandboxStatsWindowsSandboxSecurityContextWindowsNamespaceOptionWindowsPodSandboxConfigPodSandboxConfigPullImageCreateContainerL:nuxSandboxSecurityContextContainerConfigRunPodSandboxCDIDeviceMountMountPropogationIDMappingImageSpecRuntimeConfigLinuxRuntimeConfigurationCgroupDriverContainerStatsSwapUsageListContainerStatsContainerStatsLinuxPodSandboxStatsGetContainerEventsContainerEventResponseContainerStatusContainerStatusWindowsCpuUsageLinuxPodSandboxConfig无变更新增修改接口内部数据不支持WindowsMemoryUsageWindowsNetworkUsageListMetricDescriptorsListPodSandboxMetricsMetricDescriptorPodSandboxMetricsContainerMetricsMetricMetricTypeImageFsInfoImageFsInfoResponseWindowsContainerStatsWindowsProcessUsageWindowsNetworkInterfaceUsageWindowsFilesystemStatsPodSandboxStatusPodSandboxStatusResponse +\ No newline at end of file +-- +2.25.1 + diff --git a/0069-add-exec-workdir-support-for-oci-runtime.patch b/0069-add-exec-workdir-support-for-oci-runtime.patch new file mode 100644 index 0000000..e57cee6 --- /dev/null +++ b/0069-add-exec-workdir-support-for-oci-runtime.patch @@ -0,0 +1,57 @@ +From 921ee84f80adda64fb0a7125f9f709bff416945c Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Tue, 26 Dec 2023 10:17:19 +0800 +Subject: [PATCH 69/71] add exec workdir support for oci runtime + +Signed-off-by: zhongtao +--- + src/cmd/isula/stream/exec.h | 2 +- + src/cmd/isulad-shim/process.c | 4 ++++ + src/daemon/modules/runtime/isula/isula_rt_ops.c | 3 +++ + 3 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/src/cmd/isula/stream/exec.h b/src/cmd/isula/stream/exec.h +index 83a4af06..8d8e4347 100644 +--- a/src/cmd/isula/stream/exec.h ++++ b/src/cmd/isula/stream/exec.h +@@ -48,7 +48,7 @@ extern "C" { + "Username or UID (format: [:])", \ + NULL }, \ + { CMD_OPT_TYPE_STRING_DUP, false, "workdir", 0, &(cmdargs).custom_conf.workdir, \ +- "Working directory inside the container, supported only when runtime is lcr", NULL } ++ "Working directory inside the container", NULL } + + extern const char g_cmd_exec_desc[]; + extern const char g_cmd_exec_usage[]; +diff --git a/src/cmd/isulad-shim/process.c b/src/cmd/isulad-shim/process.c +index 97524f1a..06726a40 100644 +--- a/src/cmd/isulad-shim/process.c ++++ b/src/cmd/isulad-shim/process.c +@@ -1274,6 +1274,10 @@ static void get_runtime_cmd(process_t *p, const char *log_path, const char *pid_ + #endif + params[i++] = "--process"; + params[i++] = process_desc; ++ if (p->state->cwd != NULL) { ++ params[i++] = "--cwd"; ++ params[i++] = p->state->cwd; ++ } + } else { + params[i++] = "create"; + params[i++] = "--bundle"; +diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c +index fbb779f7..c754fc54 100644 +--- a/src/daemon/modules/runtime/isula/isula_rt_ops.c ++++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c +@@ -1345,6 +1345,9 @@ static int preparation_exec(const char *id, const char *runtime, const char *wor + p.runtime_args = (char **)runtime_args; + p.runtime_args_len = runtime_args_len; + copy_process(&p, process); ++ if (params->workdir != NULL) { ++ p.cwd = (char *)params->workdir; ++ } + + ret = create_process_json_file(workdir, &p); + if (ret != 0) { +-- +2.25.1 + diff --git a/0070-add-testcases-for-exec-workdir.patch b/0070-add-testcases-for-exec-workdir.patch new file mode 100644 index 0000000..38687aa --- /dev/null +++ b/0070-add-testcases-for-exec-workdir.patch @@ -0,0 +1,27 @@ +From cf7effbfaf81d1982d81bbc6ca1c5eafbc07d07b Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Tue, 26 Dec 2023 10:24:52 +0800 +Subject: [PATCH 70/71] add testcases for exec --workdir + +Signed-off-by: zhongtao +--- + CI/test_cases/container_cases/runc_exec.sh | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/CI/test_cases/container_cases/runc_exec.sh b/CI/test_cases/container_cases/runc_exec.sh +index f963724e..aa7020ee 100755 +--- a/CI/test_cases/container_cases/runc_exec.sh ++++ b/CI/test_cases/container_cases/runc_exec.sh +@@ -53,6 +53,9 @@ function exec_runc_test() + isula exec -tid $container_name /bin/sh -c 'exit 2' + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - exit code should be 0" && ((ret++)) + ++ isula exec -ti --workdir /tmp $container_name pwd | grep "/tmp" ++ [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - workdir is not /workdir failed" && ((ret++)) ++ + ls /var/run/isulad/runc/${ID}/exec/ + ls /var/run/isulad/runc/${ID}/exec/ | wc -l | grep 0 + [[ $? -ne 0 ]] && msg_err "${FUNCNAME[0]}:${LINENO} - residual dir after success exec" && ((ret++)) +-- +2.25.1 + diff --git a/0071-iSulad-restart-isuald-when-upgrade-active-isulad.patch b/0071-iSulad-restart-isuald-when-upgrade-active-isulad.patch new file mode 100644 index 0000000..033dd14 --- /dev/null +++ b/0071-iSulad-restart-isuald-when-upgrade-active-isulad.patch @@ -0,0 +1,34 @@ +From cffeca42fa88c749f122b904ecc2e634d4911576 Mon Sep 17 00:00:00 2001 +From: yangjiaqi +Date: Thu, 28 Dec 2023 15:56:47 +0800 +Subject: [PATCH 71/71] iSulad: restart isuald when upgrade active isulad + +Signed-off-by: yangjiaqi +--- + iSulad.spec | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/iSulad.spec b/iSulad.spec +index 0efbf043..71b61c8b 100644 +--- a/iSulad.spec ++++ b/iSulad.spec +@@ -196,6 +196,16 @@ if [ -e %{_unitdir}/lcrd.service.rpmsave ]; then + mv %{_unitdir}/lcrd.service.rpmsave %{_unitdir}/isulad.service + sed -i 's/lcrd/isulad/g' %{_unitdir}/isulad.service + fi ++# During the isulad upgrade process, the isulad service may still be running, but the service may be unavailable ++# due to configuration updates and other reasons. ++# it may fail if the X package is upgraded synchronously with isulad and depends on the isulad command, ++# For example syscontianer-tools and lxcfs-tools. ++# Therefore, after upgrading isulad, if the original status of isulad is running, ++# we need to restart isulad to ensure that the service is available during the upgrade process. ++systemctl status isulad | grep 'Active:' | grep 'running' ++if [ $? -eq 0 ]; then ++ systemctl restart isulad ++fi + %else + /sbin/service isulad status | grep 'Active:' | grep 'running' + if [ $? -eq 0 ]; then +-- +2.25.1 + diff --git a/iSulad.spec b/iSulad.spec new file mode 100644 index 0000000..61cb1cb --- /dev/null +++ b/iSulad.spec @@ -0,0 +1,1000 @@ +%global _version 2.1.4 +%global _release 5 +%global is_systemd 1 +%global enable_criv1 1 +%global enable_shimv2 1 +%global is_embedded 1 +%global cpp_std 17 + +Name: iSulad +Version: %{_version} +Release: %{_release} +Summary: Lightweight Container Runtime Daemon +License: Mulan PSL v2 +URL: https://gitee.com/openeuler/iSulad +Source: https://gitee.com/openeuler/iSulad/repository/archive/v%{version}.tar.gz +BuildRoot: {_tmppath}/iSulad-%{version} + +Patch0001: 0001-sandbox-del-m_containers-and-m_containersMutex.patch +Patch0002: 0002-sandbox-adapt-UT-when-del-m_containers-and-m_contain.patch +Patch0003: 0003-Add-Readonly-Masked-Path-and-RunAsGroup-support-for-.patch +Patch0004: 0004-network-support-version-opt.patch +Patch0005: 0005-doc-support-version-opt.patch +Patch0006: 0006-2242-disable-grpc-remote-connect-by-default.patch +Patch0007: 0007-2244-Save-task-address-of-shim-v2.patch +Patch0008: 0008-2233-add-runc-append-function-design-doc.patch +Patch0009: 0009-2243-Refactor-capbilities-specs.patch +Patch0010: 0010-2245-fix-utils_verify_ut-failure-when-remote-grpc-fu.patch +Patch0011: 0011-add-runc-attach-implement.patch +Patch0012: 0012-add-runc-attach-implement-unit-test-and-ci-test.patch +Patch0013: 0013-support-gcov-of-CI.patch +Patch0014: 0014-compatibility-for-manage-pods-which-created-by-old-i.patch +Patch0015: 0015-2250-Remove-PERFMON-BPF-CHECKPOINT_RESTORE.patch +Patch0016: 0016-improve-event-logs.patch +Patch0017: 0017-2251-open-ENABLE_GRPC_REMOTE_CONNECT-in-CI.patch +Patch0018: 0018-Add-compatibility-between-iSulad-and-k8s.patch +Patch0019: 0019-2254-lcr-container-with-a-damaged-config-file-will-r.patch +Patch0020: 0020-2253-bugfix-for-runc-container-exec.patch +Patch0021: 0021-bugfix-of-update-restart-policy-for-auto-remove-cont.patch +Patch0022: 0022-add-update-restart-policy-test.patch +Patch0023: 0023-2260-bugfix-for-rebuild-config.patch +Patch0024: 0024-2170-isula-image-pull.patch +Patch0025: 0025-2084-image-pull.patch +Patch0026: 0026-CI-add-ncurse-for-ubuntu-and-centos.patch +Patch0027: 0027-improve-code-of-pull-progress.patch +Patch0028: 0028-2230-format-code.patch +Patch0029: 0029-2255-Fix-cpusets-offline-issue.patch +Patch0030: 0030-modify-daemon-json-default-runtime-to-runc.patch +Patch0031: 0031-modify-CI-for-default-runtime-to-runc.patch +Patch0032: 0032-add-ut-for-devicemapper.patch +Patch0033: 0033-2275-bugfix-for-rt_lcr_rebuild_config.patch +Patch0034: 0034-2277-remove-shim-v2-format-error-log.patch +Patch0035: 0035-2276-bugfix-for-integration_check.sh.patch +Patch0036: 0036-modify-create_network.sh-for-default-runtime-changed.patch +Patch0037: 0037-modify-the-container-runtime-when-running-embedded.s.patch +Patch0038: 0038-save-sandbox-to-disk-after-network-ready.patch +Patch0039: 0039-fix-the-problem-of-abnormal-branches-not-waiting-for.patch +Patch0040: 0040-remove-embedded-image-support-in-readme.patch +Patch0041: 0041-Acquire-system-info-in-on-demand.patch +Patch0042: 0042-2268-bugfix-for-the-bliko-zero-value-exception-when-.patch +Patch0043: 0043-move-variable-declaration-out-of-loop.patch +Patch0044: 0044-2289-check-protobuf-and-grpc-version-in-cmake-for-cr.patch +Patch0045: 0045-improve-ut-for-devicemapper.patch +Patch0046: 0046-2292-bugfix-for-run.sh-and-add-build-notify-msg-for-.patch +Patch0047: 0047-2295-keep-the-service-status-unchanged-after-iSulad-.patch +Patch0048: 0048-modify-attach-socket-name.patch +Patch0049: 0049-2298-bugfix-for-hook_ignore_poststart_error-run-in-o.patch +Patch0050: 0050-2304-remove-build-and-test-in-coverage.patch +Patch0051: 0051-2303-use-a-timeout-epoll-loop-to-ensure-complete-dat.patch +Patch0052: 0052-modify-the-default-value-of-ISULAD_TMPDIR-to-var-lib.patch +Patch0053: 0053-prevent-the-parent-dir-from-being-bind-mounted-to-th.patch +Patch0054: 0054-2308-Remove-unused-header-file.patch +Patch0055: 0055-verify-the-mount-dir-first-and-then-create-tmpdir.patch +Patch0056: 0056-2300-Maintaining-a-uniform-code-style.patch +Patch0057: 0057-2312-Add-Huawei-Cloud-CodeArts-compilation-script.patch +Patch0058: 0058-bugfix-del-redundant-code.patch +Patch0059: 0059-improve-code-of-pull.patch +Patch0060: 0060-remove-var-in-coverage-and-fix-build-test-remove.patch +Patch0061: 0061-2320-improve-CI-test.patch +Patch0062: 0062-verify-name-and-digest-consistency.patch +Patch0063: 0063-code-improve-for-oci_rmi.patch +Patch0064: 0064-bugfix-for-resort_image_names.patch +Patch0065: 0065-fix-stopp-removes-cont-error-remove-inspect-error-lo.patch +Patch0066: 0066-2313-use-lxc-5.X-in-CI-testcase.patch +Patch0067: 0067-2329-modify-mount-dev-directory-for-lxc-5.X.patch +Patch0068: 0068-add-cri-1.29-api-change-docs.patch +Patch0069: 0069-add-exec-workdir-support-for-oci-runtime.patch +Patch0070: 0070-add-testcases-for-exec-workdir.patch +Patch0071: 0071-iSulad-restart-isuald-when-upgrade-active-isulad.patch + +%ifarch x86_64 aarch64 +Provides: libhttpclient.so()(64bit) +Provides: libisula_client.so()(64bit) +Provides: libisulad_tools.so()(64bit) +%endif + +%if 0%{?is_systemd} +# Systemd 230 and up no longer have libsystemd-journal +BuildRequires: pkgconfig(systemd) +Requires: systemd-units +%else +Requires(post): chkconfig +Requires(preun): chkconfig +# This is for /sbin/service +Requires(preun): initscripts +%endif + +%if 0%{?is_embedded} +BuildRequires: sqlite-devel +Requires: sqlite +%endif + +%if %{defined openeuler} +BuildRequires: gtest-devel gmock-devel +%endif + +%define lcrver_lower 2.1.3-0 +%define lcrver_upper 2.1.4-0 + +BuildRequires: libisula-devel > %{lcrver_lower} libisula-devel < %{lcrver_upper} +BuildRequires: cmake gcc-c++ yajl-devel +BuildRequires: grpc grpc-plugins grpc-devel protobuf-devel ncurses-devel +BuildRequires: libcurl libcurl-devel libarchive-devel device-mapper-devel +BuildRequires: http-parser-devel +BuildRequires: libseccomp-devel libcap-devel libselinux-devel libwebsockets libwebsockets-devel +BuildRequires: systemd-devel git +BuildRequires: libevhtp-devel libevent-devel +%if 0%{?enable_shimv2} +BuildRequires: lib-shim-v2 lib-shim-v2-devel +%endif + + +Requires: libisula > %{lcrver_lower} libisula < %{lcrver_upper} +Requires: grpc protobuf +Requires: libcurl +Requires: http-parser libseccomp +Requires: libcap libselinux libwebsockets libarchive device-mapper +Requires: systemd +Requires: (docker-runc or runc) +BuildRequires: libevhtp libevent +%if 0%{?enable_shimv2} +Requires: lib-shim-v2 +%endif + +%description +This is a umbrella project for gRPC-services based Lightweight Container +Runtime Daemon, written by C. + +%prep +%autosetup -n iSulad-v%{_version} -Sgit -p1 + +%build +mkdir -p build +cd build +%cmake \ + -DDEBUG=ON \ + -DCMAKE_SKIP_RPATH=TRUE \ + -DLIB_INSTALL_DIR=%{_libdir} \ + -DCMAKE_INSTALL_PREFIX=/usr \ +%if 0%{?enable_criv1} + -DENABLE_CRI_API_V1=ON \ + -DENABLE_SANDBOXER=ON \ +%endif +%if 0%{?enable_shimv2} + -DENABLE_SHIM_V2=ON \ +%endif +%if %{defined openeuler} + -DENABLE_UT=OFF \ +%endif + -DENABLE_GRPC_REMOTE_CONNECT=OFF \ + -DENABLE_GRPC=ON \ + -DCMAKE_CXX_STANDARD=%{cpp_std} \ + ../ + +sed -i "10 a\# undef linux" grpc/src/api/services/cri/v1alpha/api.pb.h +%if 0%{?enable_criv1} +sed -i "10 a\# undef linux" grpc/src/api/services/cri/v1/api_v1.pb.h +%endif + +%make_build + +%check +%if %{defined openeuler} +cd build +# registry_images_ut and volume_ut must run with root user +ctest -E "registry_images_ut|volume_ut" +%endif + +%install +rm -rf %{buildroot} +cd build +install -d $RPM_BUILD_ROOT/%{_libdir} +install -m 0755 ./src/libisula_client.so %{buildroot}/%{_libdir}/libisula_client.so +install -m 0755 ./src/utils/http/libhttpclient.so %{buildroot}/%{_libdir}/libhttpclient.so +install -m 0755 ./src/libisulad_tools.so %{buildroot}/%{_libdir}/libisulad_tools.so + +install -d $RPM_BUILD_ROOT/%{_libdir}/pkgconfig +install -m 0640 ./conf/isulad.pc %{buildroot}/%{_libdir}/pkgconfig/isulad.pc + +install -d $RPM_BUILD_ROOT/%{_bindir} + +install -m 0755 ./src/isula %{buildroot}/%{_bindir}/isula +install -m 0755 ./src/isulad-shim %{buildroot}/%{_bindir}/isulad-shim + +install -m 0755 ./src/isulad %{buildroot}/%{_bindir}/isulad + +install -d $RPM_BUILD_ROOT/%{_includedir}/isulad + +install -d $RPM_BUILD_ROOT/%{_sysconfdir}/isulad +install -m 0640 ../src/contrib/config/daemon.json %{buildroot}/%{_sysconfdir}/isulad/daemon.json +install -m 0440 ../src/contrib/config/daemon_constants.json %{buildroot}/%{_sysconfdir}/isulad/daemon_constants.json +install -m 0640 ../src/contrib/config/seccomp_default.json %{buildroot}/%{_sysconfdir}/isulad/seccomp_default.json + +install -d $RPM_BUILD_ROOT/%{_sysconfdir}/default/isulad +install -m 0640 ../src/contrib/config/config.json %{buildroot}/%{_sysconfdir}/default/isulad/config.json +install -m 0640 ../src/contrib/config/systemcontainer_config.json %{buildroot}/%{_sysconfdir}/default/isulad/systemcontainer_config.json +install -m 0550 ../src/contrib/sysmonitor/isulad-check.sh %{buildroot}/%{_sysconfdir}/default/isulad/isulad-check.sh + +mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/sysmonitor/process +cp ../src/contrib/sysmonitor/isulad-monit $RPM_BUILD_ROOT/etc/sysmonitor/process + +install -d $RPM_BUILD_ROOT/%{_sysconfdir}/default/isulad/hooks +install -m 0640 ../src/contrib/config/hooks/default.json %{buildroot}/%{_sysconfdir}/default/isulad/hooks/default.json + +install -d $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig +install -p -m 0640 ../src/contrib/config/iSulad.sysconfig $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig/iSulad + +%if 0%{?is_systemd} +install -d $RPM_BUILD_ROOT/%{_unitdir} +install -p -m 0640 ../src/contrib/init/isulad.service $RPM_BUILD_ROOT/%{_unitdir}/isulad.service +%else +install -d $RPM_BUILD_ROOT/%{_initddir} +install -p -m 0640 ../src/contrib/init/isulad.init $RPM_BUILD_ROOT/%{_initddir}/isulad.init +%endif + +%clean +rm -rf %{buildroot} + +%pre +# support update from lcrd to isulad, will remove in next version +if [ "$1" = "2" ]; then +%if 0%{?is_systemd} +systemctl stop lcrd &>/dev/null +systemctl disable lcrd &>/dev/null +if [ -e %{_sysconfdir}/isulad/daemon.json ];then + sed -i 's#/etc/default/lcrd/hooks#/etc/default/isulad/hooks#g' %{_sysconfdir}/isulad/daemon.json +fi +%else +/sbin/chkconfig --del lcrd &>/dev/null +%endif +fi + +%post +if ! getent group isula > /dev/null; then + groupadd --system isula +fi + +if [ "$1" = "1" ]; then +%if 0%{?is_systemd} +systemctl enable isulad +systemctl start isulad +%else +/sbin/chkconfig --add isulad +%endif +elif [ "$1" = "2" ]; then +%if 0%{?is_systemd} +# support update from lcrd to isulad, will remove in next version +if [ -e %{_unitdir}/lcrd.service.rpmsave ]; then + mv %{_unitdir}/lcrd.service.rpmsave %{_unitdir}/isulad.service + sed -i 's/lcrd/isulad/g' %{_unitdir}/isulad.service +fi +# During the isulad upgrade process, the isulad service may still be running, but the service may be unavailable +# due to configuration updates and other reasons. +# it may fail if the X package is upgraded synchronously with isulad and depends on the isulad command, +# For example syscontianer-tools and lxcfs-tools. +# Therefore, after upgrading isulad, if the original status of isulad is running, +# we need to restart isulad to ensure that the service is available during the upgrade process. +systemctl status isulad | grep 'Active:' | grep 'running' +if [ $? -eq 0 ]; then + systemctl restart isulad +fi +%else +/sbin/service isulad status | grep 'Active:' | grep 'running' +if [ $? -eq 0 ]; then + /sbin/service isulad restart +fi +%endif +fi + +if ! getent group isula > /dev/null; then + groupadd --system isula +fi + +%preun +%if 0%{?is_systemd} +%systemd_preun isulad +%else +if [ $1 -eq 0 ] ; then + /sbin/service isulad stop >/dev/null 2>&1 + /sbin/chkconfig --del isulad +fi +%endif + +%postun +%if 0%{?is_systemd} +%systemd_postun_with_restart isulad +%else +if [ "$1" -ge "1" ] ; then + /sbin/service isulad condrestart >/dev/null 2>&1 || : +fi +%endif + +%files +%attr(0600,root,root) %{_sysconfdir}/sysmonitor/process/isulad-monit +%attr(0550,root,root) %{_sysconfdir}/default/isulad/isulad-check.sh +%defattr(0640,root,root,0750) +%{_sysconfdir}/isulad +%{_sysconfdir}/isulad/* +%{_sysconfdir}/default/* +%defattr(-,root,root,-) +%if 0%{?is_systemd} +%{_unitdir}/isulad.service +%attr(0640,root,root) %{_unitdir}/isulad.service +%else +%{_initddir}/isulad.init +%attr(0640,root,root) %{_initddir}/isulad.init +%endif +%attr(0755,root,root) %{_libdir}/pkgconfig +%attr(0640,root,root) %{_libdir}/pkgconfig/isulad.pc +%defattr(0755,root,root,0755) +%{_bindir}/* +%{_libdir}/* +%attr(0640,root,root) %{_sysconfdir}/sysconfig/iSulad +%attr(0640,root,root) %{_sysconfdir}/isulad/daemon.json + +%config(noreplace,missingok) %{_sysconfdir}/sysconfig/iSulad +%config(noreplace,missingok) %{_sysconfdir}/isulad/daemon.json +%if 0%{?is_systemd} +%config(noreplace,missingok) %{_unitdir}/isulad.service +%else +%config(noreplace,missingok) %{_initddir}/isulad.init +%endif + +%changelog +* Fri Dec 29 2023 yangjiaqi - 2.1.4-5 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: keep the service status unchanged after iSulad service upgrade + +* Thu Dec 28 2023 leizhongkai - 2.1.4-4 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: upgrade from upstream + +* Wed Dec 20 2023 zhongtao - 2.1.4-3 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: upgrade from upstream + +* Wed Nov 15 2023 zhongtao - 2.1.4-2 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: delete libisulad_img.so and compilation dependency: lxc, and add running dependency:runc + +* Tue Nov 14 2023 zhongtao - 2.1.4-1 +- Type: update +- ID: NA +- SUG: NA +- DESC: update to v2.1.4 + +* Wed Sep 13 2023 xuxuepeng - 2.1.3-2 +- Type: update +- ID: NA +- SUG: NA +- DESC: Add vsock support for exec + +* Tue Aug 29 2023 xuxuepeng - 2.1.3-1 +- Type: update +- ID: NA +- SUG: NA +- DESC: update to v2.1.3 + +* Mon Aug 28 2023 zhangxiaoyu - 2.1.2-8 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: modify lxc dependence to docker-runc dependence + +* Mon Aug 21 2023 zhangxiaoyu - 2.1.2-7 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: enable grpc and fix compile failed + +* Wed Aug 09 2023 zhangxiaoyu - 2.1.2-6 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: modify daemon json default runtime to runc + +* Thu Jul 20 2023 zhangxiaoyu - 2.1.2-5 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: compile using c++17 + +* Mon May 29 2023 zhangxiaoyu - 2.1.2-4 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: bugfix for memleak and malloc + +* Thu May 25 2023 zhongtao - 2.1.2-3 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: upgrade from upstream + +* Fri May 12 2023 zhangxiaoyu - 2.1.2-2 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: fix remote grpc macro + +* Thu May 11 2023 zhangxiaoyu - 2.1.2-1 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: update from upstream to update cri + +* Fri Mar 24 2023 wangrunze - 2.1.1-6 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: update from upstream to include remote feature + +* Thu Mar 16 2023 zhangxiaoyu - 2.1.1-5 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: use CURLOPT_XFERINFOFUNCTION instead of deprecated CURLOPT_PROGRESSFUNCTION since curl 7.32.0 + +* Wed Feb 22 2023 zhangxiaoyu - 2.1.1-4 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: upgrade from upstream + +* Thu Feb 16 2023 zhangxiaoyu - 2.1.1-3 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: add check + +* Mon Feb 06 2023 zhangxiaoyu - 2.1.1-2 +- Type: update +- ID: NA +- SUG: NA +- DESC: modify dependence from lcr to libisula + +* Mon Feb 06 2023 zhangxiaoyu - 2.1.1-1 +- Type: update +- ID: NA +- SUG: NA +- DESC: update to v2.1.1 + +* Tue Jan 03 2023 zhangxiaoyu - 2.0.18-1 +- Type: update +- ID: NA +- SUG: NA +- DESC: update to v2.0.18 + +* Thu Dec 22 2022 zhangxiaoyu - 2.0.17-14 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: remove clean_module_fill_ctx for libisulad_img.so + +* Mon Dec 19 2022 zhangxiaoyu - 2.0.17-13 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: update lcr dependence version + +* Fri Dec 16 2022 zhangxiaoyu - 2.0.17-12 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: update from upstream + +* Tue Dec 06 2022 zhangxiaoyu - 2.0.17-11 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: update from upstream + +* Mon Nov 28 2022 yangjiaqi - 2.0.17-10 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: remove chmod 751 permission for dirs by engine when user-remap enabled + +* Fri Nov 25 2022 zhangxiaoyu - 2.0.17-9 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: add primary group to additional groups + +* Mon Nov 21 2022 zhangxiaoyu - 2.0.17-8 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: fix cannot install isulad and unknown option + +* Wed Nov 16 2022 zhangxiaoyu - 2.0.17-7 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: update tar package from source + +* Wed Nov 02 2022 wangrunze - 2.0.17-6 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: fix cleanup module memory leak + +* Tue Nov 01 2022 zhangxiaoyu - 2.0.17-5 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: add ut and bugfix for device mapper and websocket + +* Mon Oct 31 2022 wujing - 2.0.17-4 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: sync from openEuler + +* Wed Oct 19 2022 zhangxiaoyu - 2.0.17-3 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: add required package lcr clibcni lower and upper version + +* Mon Oct 10 2022 zhangxiaoyu - 2.0.17-2 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: use epoll instead of select for wait_exit_fifo + +* Sun Oct 09 2022 zhangxiaoyu - 2.0.17-1 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: update iSulad version to 2.0.17-1 + +* Thu Sep 29 2022 haozi007 - 2.0.16-8 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: sync from openEuler + +* Tue Sep 20 2022 zhangxiaoyu - 2.0.16-7 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: change libisulad_tools.so mode + +* Thu Sep 15 2022 zhangxiaoyu - 2.0.16-6 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: shield upgrade error if lcrd not exist + +* Tue Sep 13 2022 zhangxiaoyu - 2.0.16-5 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: calculate timezone by tm_gmtoff + +* Thu Sep 08 2022 zhangxiaoyu - 2.0.16-4 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: invalid free default-runtime and cri-runtime after free json-confs + +* Wed Sep 07 2022 zhangxiaoyu - 2.0.16-3 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: sycn patches from openeuler/iSulad + +* Tue Aug 30 2022 leizhongkai - 2.0.16-2 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: sync from upstream openeuler/iSulad + +* Tue Aug 23 2022 wangfengtu - 2.0.16-1 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: update iSulad version to 2.0.16-1 + +* Mon Aug 22 2022 zhongtao - 2.0.15-6 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: remove rpath by cmake + +* Wed Aug 17 2022 haozi007 - 2.0.15-5 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: sycn patches from openeuler + +* Mon Aug 15 2022 wangfengtu - 2.0.15-4 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: change default umask to 0022 + +* Tue Aug 9 2022 haozi007 - 2.0.15-3 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: sycn patches from openeuler + +* Mon Aug 1 2022 chengzeruizhi - 2.0.15-2 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: sycn patches from openeuler branch + +* Fri Jul 8 2022 haozi007 - 2.0.15-1 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: update version to v2.0.15 + +* Fri Jul 8 2022 haozi007 - 2.0.14-11 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: add limit to lcr version + +* Wed Jun 22 2022 yangjiaqi - 2.0.14-10 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: sync from upstream openeuler/iSulad + +* Tue Jun 21 2022 zhangxiaoyu - 2.0.14-9 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: sync from upstream openeuler/iSulad + +* Wed Jun 15 2022 chengzeruizhi - 2.0.14-8 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: sync from upstream openeuler/iSulad + +* Tue May 31 2022 zhangxiaoyu - 2.0.14-7 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: fix type convert, add null pointer check, remove unuse macro + +* Tue May 31 2022 zhangxiaoyu - 2.0.14-6 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: fix different type convert and add check to arguments + +* Mon May 30 2022 chengzrz - 2.0.14-5 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: seccomp optimization + +* Fri May 27 2022 haozi007 - 2.0.14-4 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: improve fuzz test for pw and gr parser + +* Tue May 24 2022 wangfengtu - 2.0.14-3 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: fix install error when android + +* Tue May 24 2022 wangfengtu - 2.0.14-2 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: do not mkdir of isulad if no controller found + +* Mon May 23 2022 haozi007 - 2.0.14-1 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: update version to v2.0.14 + +* Mon May 16 2022 haozi007 - 2.0.13-5 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: sync from upstream openEuler/iSulad + +* Tue May 10 2022 hejunjie - 2.0.13-4 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: bionic adaptation, increase lcov coverage + +* Thu May 5 2022 hejunjie - 2.0.13-3 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: bionic adaptation for pwgr obj parser + +* Mon Apr 25 2022 zhangxiaoyu - 2.0.13-2 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: sync from upstream + +* Mon Apr 18 2022 wangfengtu - 2.0.13-1 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: update version to v2.0.13 + +* Fri Mar 25 2022 wangfengtu - 2.0.12-1 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: update version to v2.0.12 + +* Thu Mar 17 2022 haozi007 - 2.0.11-6 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: remove unnecessary error message + +* Thu Mar 17 2022 wangfengtu - 2.0.11-5 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: fix uid/gid error when load image + +* Wed Mar 09 2022 wangfengtu - 2.0.11-4 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: add provides of libisulad_tools.so + +* Thu Mar 03 2022 wangfengtu - 2.0.11-3 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: Add the function of isolating the user namespaces + +* Thu Mar 03 2022 wangfengtu - 2.0.11-2 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: add libisulad_tools.so + +* Thu Feb 24 2022 wangfengtu - 2.0.11-1 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: update version to v2.0.11 + +* Wed Jan 12 2022 wangfengtu - 2.0.10-15 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: fix compile error of isula-transform + +* Wed Jan 12 2022 zhangxiaoyu - 2.0.10-14 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: fix compile error with grpc 1.41.x + +* Tue Jan 4 2022 wangfengtu - 2.0.10-13 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: fix compile error when building embedded image + +* Mon Dec 27 2021 wangfengtu - 2.0.10-12 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: sync patches from upstream + +* Thu Dec 09 2021 chengzeruizhi - 2.0.10-11 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: fixed a bug that occurs when starting a container in host mode + +* Thu Dec 09 2021 wangfengtu - 2.0.10-10 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: remove dependance of sqlite + +* Mon Dec 06 2021 gaohuatao - 2.0.10-9 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: specify version + +* Fri Dec 03 2021 wangfengtu - 2.0.10-8 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: fix undefined reference to `service_arguments_free' in libisulad_img.so + +* Thu Dec 02 2021 wangfengtu - 2.0.10-7 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: sync patches from upstream + +* Tue Nov 23 2021 chengzeruizhi - 2.0.10-6 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: modify the procedure of running a pod + +* Fri Nov 19 2021 gaohuatao - 2.0.10-5 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: sync from upstream + +* Fri Nov 19 2021 wangfengtu - 2.0.10-4 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: fix memleak when use multiple --volumes-from + +* Tue Nov 16 2021 wujing - 2.0.10-3 +- Type: enhancement +- ID: NA +- SUG: NA +- DESC: add shimv2 build switch + +* Tue Nov 16 2021 wujing - 2.0.10-2 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: remove build platform restrictions + +* Tue Nov 09 2021 gaohuatao - 2.0.10-1 +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: update from openeuler + +* Tue Oct 19 2021 wangfengtu - 2.0.9-20211019.121837.gitf067b3ce +- Type: bugfix +- ID: NA +- SUG: NA +- DESC: strip sha256 prefix when decrease hold references + +* Fri Jun 25 2021 wujing - 2.0.9-20210625.165022.git5a088d9c +- Type: update to v2.0.9 +- ID: NA +- SUG: NA +- DESC: update from master + +* Tue May 18 2021 wangfengtu - 2.0.8-20210518.144540.git5288ed92 +- Type: sync from upstream +- ID: NA +- SUG: NA +- DESC: update from master + +* Fri Mar 26 2021 zhangxiaoyu - 2.0.8-20210326.094027.gitac974aa6 +- Type: sync from upstream +- ID: NA +- SUG: NA +- DESC: update from master + +* Tue Mar 23 2021 haozi007 - 20210323.094917.git7e6aa593 +- Type: sync from upstream +- ID: NA +- SUG: NA +- DESC: update from master + +* Tue Feb 2 2021 lifeng - 2.0.8-20210202.153251.gite082dcf3 +- Type: sync from upstream +- ID: NA +- SUG: NA +- DESC: update from master + +* Mon Jan 18 2021 lifeng - 2.0.8-20210118.195254.git077e10f2 +- Type: sync from upstream +- ID: NA +- SUG: NA +- DESC: update from master + +* Wed Dec 30 2020 lifeng - 2.0.8-20201230.155843.git6557a6eb +- Type: update to v2.0.8 +- ID: NA +- SUG: NA +- DESC: update from master + +* Mon Dec 7 2020 zhangxiaoyu - 2.0.7-20201207.151847.gita1fce123 +- Type: update +- ID: NA +- SUG: NA +- DESC: update from master + +* Sat Dec 5 2020 lifeng - 2.0.7-20201205.145752.gita461cc51 +- Type: bugfix +- ID:NA +- SUG:NA +- DESC: ignore list containers errors + +* Thu Dec 3 2020 haozi007 - 2.0.7-20201203.190902.git48f598fd +- Type:update from master +- ID:NA +- SUG:NA +- DESC: update from master + +* Sat Nov 28 2020 lifeng - 2.0.7-20201128.095506.git1e1623a5 +- Type: bugfix +- ID:NA +- SUG:NA +- DESC: Mounts: only qsort the configed mounts and make possible to bind mount /proc and /sys/fs. +- related lxc PR fixed: +- 1.add check whether have /proc mounts entry, if has, skip the auto +- 2.mount cgroup before do mount entrys +- 3.pass if the mount on top of /proc and the source of the mount is a proc filesystem + +* Wed Nov 25 2020 wangfengtu - 2.0.7-20201125.165149.git7d150c3c +- Type: bugfix +- ID:NA +- SUG:NA +- DESC: update from openeuler + +* Wed Nov 25 2020 wangfengtu - 2.0.6-20201125.160534.git9fb5e75d +- Type: bugfix +- ID:NA +- SUG:NA +- DESC: fix rpath not work + +* Thu Nov 12 2020 gaohuatao - 2.0.6-20201112.193005.git8a6b73c8 +- Type: update from openeuler +- ID:NA +- SUG:NA +- DESC: update from openeuler + +* Wed Oct 14 2020 lifeng68 - 2.0.6-20201014.152749.gitc8a43925 +- Type: upgrade to v2.0.6 +- ID:NA +- SUG:NA +- DESC: upgrade to v2.0.6 + +* Fri Sep 18 2020 - 2.0.5-20200918.112827.git9aea9b75 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC: modify log level to warn + +* Mon Sep 14 2020 - 2.0.5-20200914.172527.gitae86920a +- Type:bugfix +- ID:NA +- SUG:NA +- DESC: remove unused config + +* Thu Sep 10 2020 - 2.0.5-20200910.144345.git71b1055b +- Type:enhancement +- ID:NA +- SUG:NA +- DESC: add chrpath + +* Fri Sep 04 2020 zhangxiaoyu - 2.0.5-20200904.114315.gitff1761c3 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC: upgrade from v2.0.3 to v2.0.5 + +* Wed Sep 02 2020 YoungJQ - 2.0.3-20200902.114727.git6d945f26 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC: modify source0 address diff --git a/sources b/sources new file mode 100644 index 0000000..ed79dd4 --- /dev/null +++ b/sources @@ -0,0 +1 @@ +bc668d146a03204fdc5db3cae5c3dedf v2.1.4.tar.gz -- cgit v1.2.3