From ad9fca616632a6ec554270526ca582738ccc325c Mon Sep 17 00:00:00 2001 From: zhongtao Date: Sun, 4 Feb 2024 02:17:02 +0000 Subject: [PATCH] !658 update to v2.1.5 * update to v2.1.5 --- 0001-code-improve-for-sandbox.cc.patch | 27 + ...l-m_containers-and-m_containersMutex.patch | 347 -- ...r-with-protobuf-25.1-and-grpc-1.60.x.patch | 255 ++ ...-when-del-m_containers-and-m_contain.patch | 167 - ...ked-Path-and-RunAsGroup-support-for-.patch | 642 --- ...-point-remains-under-special-circums.patch | 123 + ...anup-if-the-directory-does-not-exist.patch | 71 + 0004-network-support-version-opt.patch | 482 --- 0005-doc-support-version-opt.patch | 87 - ...letes-the-temporary-files-it-creates.patch | 151 + ...sable-grpc-remote-connect-by-default.patch | 26 - 0006-skip-devmapper-ut.patch | 26 + 0007-2244-Save-task-address-of-shim-v2.patch | 209 - ...-add-runc-append-function-design-doc.patch | 110 - 0009-2243-Refactor-capbilities-specs.patch | 1056 ----- ...erify_ut-failure-when-remote-grpc-fu.patch | 33 - 0011-add-runc-attach-implement.patch | 1312 ------- ...tach-implement-unit-test-and-ci-test.patch | 242 -- 0013-support-gcov-of-CI.patch | 26 - ...r-manage-pods-which-created-by-old-i.patch | 163 - ...emove-PERFMON-BPF-CHECKPOINT_RESTORE.patch | 33 - 0016-improve-event-logs.patch | 202 - ...pen-ENABLE_GRPC_REMOTE_CONNECT-in-CI.patch | 57 - ...compatibility-between-iSulad-and-k8s.patch | 57 - ...er-with-a-damaged-config-file-will-r.patch | 384 -- ...-2253-bugfix-for-runc-container-exec.patch | 39 - ...-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 - ...-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 --- ...-daemon-json-default-runtime-to-runc.patch | 52 - ...odify-CI-for-default-runtime-to-runc.patch | 815 ---- 0032-add-ut-for-devicemapper.patch | 737 ---- ...275-bugfix-for-rt_lcr_rebuild_config.patch | 46 - ...2277-remove-shim-v2-format-error-log.patch | 25 - ...2276-bugfix-for-integration_check.sh.patch | 26 - ...twork.sh-for-default-runtime-changed.patch | 40 - ...iner-runtime-when-running-embedded.s.patch | 141 - ...-sandbox-to-disk-after-network-ready.patch | 68 - ...of-abnormal-branches-not-waiting-for.patch | 153 - ...ove-embedded-image-support-in-readme.patch | 62 - 0041-Acquire-system-info-in-on-demand.patch | 392 -- ...the-bliko-zero-value-exception-when-.patch | 92 - ...ove-variable-declaration-out-of-loop.patch | 34 - ...buf-and-grpc-version-in-cmake-for-cr.patch | 40 - 0045-improve-ut-for-devicemapper.patch | 381 -- ...run.sh-and-add-build-notify-msg-for-.patch | 56 - ...rvice-status-unchanged-after-iSulad-.patch | 251 -- 0048-modify-attach-socket-name.patch | 40 - ...hook_ignore_poststart_error-run-in-o.patch | 110 - ...04-remove-build-and-test-in-coverage.patch | 28 - ...ut-epoll-loop-to-ensure-complete-dat.patch | 197 - ...lt-value-of-ISULAD_TMPDIR-to-var-lib.patch | 170 - ...nt-dir-from-being-bind-mounted-to-th.patch | 58 - 0054-2308-Remove-unused-header-file.patch | 25 - ...unt-dir-first-and-then-create-tmpdir.patch | 43 - ...300-Maintaining-a-uniform-code-style.patch | 26 - ...ei-Cloud-CodeArts-compilation-script.patch | 36 - 0058-bugfix-del-redundant-code.patch | 26 - 0059-improve-code-of-pull.patch | 71 - ...n-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 - ...s-cont-error-remove-inspect-error-lo.patch | 76 - 0066-2313-use-lxc-5.X-in-CI-testcase.patch | 41 - ...dify-mount-dev-directory-for-lxc-5.X.patch | 27 - 0068-add-cri-1.29-api-change-docs.patch | 139 - ...exec-workdir-support-for-oci-runtime.patch | 57 - 0070-add-testcases-for-exec-workdir.patch | 27 - ...rt-isuald-when-upgrade-active-isulad.patch | 34 - iSulad.spec | 91 +- v2.1.4.tar.gz => v2.1.5.tar.gz | Bin 11709828 -> 11912415 bytes 79 files changed, 669 insertions(+), 17644 deletions(-) create mode 100644 0001-code-improve-for-sandbox.cc.patch delete mode 100644 0001-sandbox-del-m_containers-and-m_containersMutex.patch create mode 100644 0002-fix-compile-error-with-protobuf-25.1-and-grpc-1.60.x.patch delete mode 100644 0002-sandbox-adapt-UT-when-del-m_containers-and-m_contain.patch delete mode 100644 0003-Add-Readonly-Masked-Path-and-RunAsGroup-support-for-.patch create mode 100644 0003-bugfix-for-mount-point-remains-under-special-circums.patch create mode 100644 0004-do-not-cleanup-if-the-directory-does-not-exist.patch delete mode 100644 0004-network-support-version-opt.patch delete mode 100644 0005-doc-support-version-opt.patch create mode 100644 0005-module-only-deletes-the-temporary-files-it-creates.patch delete mode 100644 0006-2242-disable-grpc-remote-connect-by-default.patch create mode 100644 0006-skip-devmapper-ut.patch delete mode 100644 0007-2244-Save-task-address-of-shim-v2.patch delete mode 100644 0008-2233-add-runc-append-function-design-doc.patch delete mode 100644 0009-2243-Refactor-capbilities-specs.patch delete mode 100644 0010-2245-fix-utils_verify_ut-failure-when-remote-grpc-fu.patch delete mode 100644 0011-add-runc-attach-implement.patch delete mode 100644 0012-add-runc-attach-implement-unit-test-and-ci-test.patch delete mode 100644 0013-support-gcov-of-CI.patch delete mode 100644 0014-compatibility-for-manage-pods-which-created-by-old-i.patch delete mode 100644 0015-2250-Remove-PERFMON-BPF-CHECKPOINT_RESTORE.patch delete mode 100644 0016-improve-event-logs.patch delete mode 100644 0017-2251-open-ENABLE_GRPC_REMOTE_CONNECT-in-CI.patch delete mode 100644 0018-Add-compatibility-between-iSulad-and-k8s.patch delete mode 100644 0019-2254-lcr-container-with-a-damaged-config-file-will-r.patch delete mode 100644 0020-2253-bugfix-for-runc-container-exec.patch delete mode 100644 0021-bugfix-of-update-restart-policy-for-auto-remove-cont.patch delete mode 100644 0022-add-update-restart-policy-test.patch delete mode 100644 0023-2260-bugfix-for-rebuild-config.patch delete mode 100644 0024-2170-isula-image-pull.patch delete mode 100644 0025-2084-image-pull.patch delete mode 100644 0026-CI-add-ncurse-for-ubuntu-and-centos.patch delete mode 100644 0027-improve-code-of-pull-progress.patch delete mode 100644 0028-2230-format-code.patch delete mode 100644 0029-2255-Fix-cpusets-offline-issue.patch delete mode 100644 0030-modify-daemon-json-default-runtime-to-runc.patch delete mode 100644 0031-modify-CI-for-default-runtime-to-runc.patch delete mode 100644 0032-add-ut-for-devicemapper.patch delete mode 100644 0033-2275-bugfix-for-rt_lcr_rebuild_config.patch delete mode 100644 0034-2277-remove-shim-v2-format-error-log.patch delete mode 100644 0035-2276-bugfix-for-integration_check.sh.patch delete mode 100644 0036-modify-create_network.sh-for-default-runtime-changed.patch delete mode 100644 0037-modify-the-container-runtime-when-running-embedded.s.patch delete mode 100644 0038-save-sandbox-to-disk-after-network-ready.patch delete mode 100644 0039-fix-the-problem-of-abnormal-branches-not-waiting-for.patch delete mode 100644 0040-remove-embedded-image-support-in-readme.patch delete mode 100644 0041-Acquire-system-info-in-on-demand.patch delete mode 100644 0042-2268-bugfix-for-the-bliko-zero-value-exception-when-.patch delete mode 100644 0043-move-variable-declaration-out-of-loop.patch delete mode 100644 0044-2289-check-protobuf-and-grpc-version-in-cmake-for-cr.patch delete mode 100644 0045-improve-ut-for-devicemapper.patch delete mode 100644 0046-2292-bugfix-for-run.sh-and-add-build-notify-msg-for-.patch delete mode 100644 0047-2295-keep-the-service-status-unchanged-after-iSulad-.patch delete mode 100644 0048-modify-attach-socket-name.patch delete mode 100644 0049-2298-bugfix-for-hook_ignore_poststart_error-run-in-o.patch delete mode 100644 0050-2304-remove-build-and-test-in-coverage.patch delete mode 100644 0051-2303-use-a-timeout-epoll-loop-to-ensure-complete-dat.patch delete mode 100644 0052-modify-the-default-value-of-ISULAD_TMPDIR-to-var-lib.patch delete mode 100644 0053-prevent-the-parent-dir-from-being-bind-mounted-to-th.patch delete mode 100644 0054-2308-Remove-unused-header-file.patch delete mode 100644 0055-verify-the-mount-dir-first-and-then-create-tmpdir.patch delete mode 100644 0056-2300-Maintaining-a-uniform-code-style.patch delete mode 100644 0057-2312-Add-Huawei-Cloud-CodeArts-compilation-script.patch delete mode 100644 0058-bugfix-del-redundant-code.patch delete mode 100644 0059-improve-code-of-pull.patch delete mode 100644 0060-remove-var-in-coverage-and-fix-build-test-remove.patch delete mode 100644 0061-2320-improve-CI-test.patch delete mode 100644 0062-verify-name-and-digest-consistency.patch delete mode 100644 0063-code-improve-for-oci_rmi.patch delete mode 100644 0064-bugfix-for-resort_image_names.patch delete mode 100644 0065-fix-stopp-removes-cont-error-remove-inspect-error-lo.patch delete mode 100644 0066-2313-use-lxc-5.X-in-CI-testcase.patch delete mode 100644 0067-2329-modify-mount-dev-directory-for-lxc-5.X.patch delete mode 100644 0068-add-cri-1.29-api-change-docs.patch delete mode 100644 0069-add-exec-workdir-support-for-oci-runtime.patch delete mode 100644 0070-add-testcases-for-exec-workdir.patch delete mode 100644 0071-iSulad-restart-isuald-when-upgrade-active-isulad.patch rename v2.1.4.tar.gz => v2.1.5.tar.gz (61%) diff --git a/0001-code-improve-for-sandbox.cc.patch b/0001-code-improve-for-sandbox.cc.patch new file mode 100644 index 0000000..8b3d678 --- /dev/null +++ b/0001-code-improve-for-sandbox.cc.patch @@ -0,0 +1,27 @@ +From 9497e03709a035805effd96eaa21f6c221a79e94 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Fri, 19 Jan 2024 17:12:30 +0800 +Subject: [PATCH 1/6] code improve for sandbox.cc + +Signed-off-by: zhongtao +--- + src/daemon/sandbox/sandbox.cc | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/daemon/sandbox/sandbox.cc b/src/daemon/sandbox/sandbox.cc +index 359cfbad..7b6496ed 100644 +--- a/src/daemon/sandbox/sandbox.cc ++++ b/src/daemon/sandbox/sandbox.cc +@@ -1086,8 +1086,7 @@ 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()); + +- google::protobuf::util::MessageToJsonString(*m_sandboxConfig.get(), &jsonStr); +- if (jsonStr.length() == 0) { ++ if (!google::protobuf::util::MessageToJsonString(*m_sandboxConfig.get(), &jsonStr).ok()) { + error.Errorf("Failed to get sandbox config json for sandbox: '%s'", m_id.c_str()); + ERROR("Failed to get sandbox config json for sandbox: '%s'", m_id.c_str()); + } +-- +2.25.1 + diff --git a/0001-sandbox-del-m_containers-and-m_containersMutex.patch b/0001-sandbox-del-m_containers-and-m_containersMutex.patch deleted file mode 100644 index 84c3455..0000000 --- a/0001-sandbox-del-m_containers-and-m_containersMutex.patch +++ /dev/null @@ -1,347 +0,0 @@ -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-fix-compile-error-with-protobuf-25.1-and-grpc-1.60.x.patch b/0002-fix-compile-error-with-protobuf-25.1-and-grpc-1.60.x.patch new file mode 100644 index 0000000..beebaaf --- /dev/null +++ b/0002-fix-compile-error-with-protobuf-25.1-and-grpc-1.60.x.patch @@ -0,0 +1,255 @@ +From 71f8d4accbec5153b362281bbaf9a516ccd083f5 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Mon, 22 Jan 2024 15:55:16 +0800 +Subject: [PATCH 2/6] fix compile error with protobuf 25.1 and grpc 1.60.x + +Signed-off-by: zhongtao +--- + cmake/checker.cmake | 76 +++++++++++++++++++ + cmake/protoc.cmake | 3 - + src/CMakeLists.txt | 12 +-- + .../sandbox/controller/manager/CMakeLists.txt | 4 +- + .../sandboxer/async_wait_call/CMakeLists.txt | 4 +- + .../sandboxer/sandboxer_client/CMakeLists.txt | 4 +- + .../sandboxer_controller/CMakeLists.txt | 4 +- + test/sandbox/controller/shim/CMakeLists.txt | 4 +- + test/sandbox/sandbox/CMakeLists.txt | 4 +- + test/sandbox/sandbox_manager/CMakeLists.txt | 4 +- + 10 files changed, 87 insertions(+), 32 deletions(-) + +diff --git a/cmake/checker.cmake b/cmake/checker.cmake +index e19618e4..b0c395ef 100644 +--- a/cmake/checker.cmake ++++ b/cmake/checker.cmake +@@ -154,7 +154,83 @@ if (GRPC_CONNECTOR) + find_library(GPR_LIBRARY gpr) + _CHECK(GPR_LIBRARY "GPR_LIBRARY-NOTFOUND" "libgpr.so") + # no check ++ ++ # The use of absl libraries depends on the version of protobuf and grpc. ++ # Versions of protobuf before v22.0 do not require absl libraries at all. ++ # However, versions after v22.0 require the support of absl libraries. ++ # As a result, we skip the check for absl libraries in order to accommodate different protobuf and grpc versions. ++ set(ISULAD_ABSL_USED_TARGETS) + find_library(ABSL_SYNC_LIB absl_synchronization) ++ if (ABSL_SYNC_LIB) ++ set(ISULAD_ABSL_USED_TARGETS ++ ${ISULAD_ABSL_USED_TARGETS} ++ ${ABSL_SYNC_LIB} ++ ) ++ endif() ++ ++ find_library(ABSL_CORD_LIB absl_cord) ++ if (ABSL_CORD_LIB) ++ set(ISULAD_ABSL_USED_TARGETS ++ ${ISULAD_ABSL_USED_TARGETS} ++ ${ABSL_CORD_LIB} ++ ) ++ endif() ++ ++ find_library(ABSL_CORDZ_FUNCTIONS_LIB absl_cordz_functions) ++ if (ABSL_CORDZ_FUNCTIONS_LIB) ++ set(ISULAD_ABSL_USED_TARGETS ++ ${ISULAD_ABSL_USED_TARGETS} ++ ${ABSL_CORDZ_FUNCTIONS_LIB} ++ ) ++ endif() ++ ++ find_library(ABSL_CORDZ_INFO_LIB absl_cordz_info) ++ if (ABSL_CORDZ_INFO_LIB) ++ set(ISULAD_ABSL_USED_TARGETS ++ ${ISULAD_ABSL_USED_TARGETS} ++ ${ABSL_CORDZ_INFO_LIB} ++ ) ++ endif() ++ ++ find_library(ABSL_HASH_LIB absl_hash) ++ if (ABSL_HASH_LIB) ++ set(ISULAD_ABSL_USED_TARGETS ++ ${ISULAD_ABSL_USED_TARGETS} ++ ${ABSL_HASH_LIB} ++ ) ++ endif() ++ ++ find_library(ABSL_LOG_INTERNAL_CHECK_OP_LIB absl_log_internal_check_op) ++ if (ABSL_LOG_INTERNAL_CHECK_OP_LIB) ++ set(ISULAD_ABSL_USED_TARGETS ++ ${ISULAD_ABSL_USED_TARGETS} ++ ${ABSL_LOG_INTERNAL_CHECK_OP_LIB} ++ ) ++ endif() ++ ++ find_library(ABSL_LOG_INTERNAL_MESSAGE_LIB absl_log_internal_message) ++ if (ABSL_LOG_INTERNAL_MESSAGE_LIB) ++ set(ISULAD_ABSL_USED_TARGETS ++ ${ISULAD_ABSL_USED_TARGETS} ++ ${ABSL_LOG_INTERNAL_MESSAGE_LIB} ++ ) ++ endif() ++ ++ find_library(ABSL_LOG_INTERNAL_NULLGUARD_LIB absl_log_internal_nullguard) ++ if (ABSL_LOG_INTERNAL_NULLGUARD_LIB) ++ set(ISULAD_ABSL_USED_TARGETS ++ ${ISULAD_ABSL_USED_TARGETS} ++ ${ABSL_LOG_INTERNAL_NULLGUARD_LIB} ++ ) ++ endif() ++ ++ find_library(ABSL_STATUS_LIB absl_status) ++ if (ABSL_STATUS_LIB) ++ set(ISULAD_ABSL_USED_TARGETS ++ ${ISULAD_ABSL_USED_TARGETS} ++ ${ABSL_STATUS_LIB} ++ ) ++ endif() + + # check websocket + find_path(WEBSOCKET_INCLUDE_DIR libwebsockets.h) +diff --git a/cmake/protoc.cmake b/cmake/protoc.cmake +index 80c08687..6e2d1b84 100644 +--- a/cmake/protoc.cmake ++++ b/cmake/protoc.cmake +@@ -69,9 +69,6 @@ endif() + + if (ENABLE_CRI_API_V1 AND ENABLE_SANDBOXER) + execute_process(COMMAND mkdir -p ${SANDBOX_PROTOS_OUT_PATH}) +- PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/google/protobuf/any.proto) +- PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/google/protobuf/empty.proto) +- PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/google/protobuf/timestamp.proto) + PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox/types/sandbox.proto) + PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox/types/mount.proto) + PROTOC_CPP_GEN(sandbox ${SANDBOX_PROTOS_OUT_PATH} ${PROTOS_PATH}/sandbox/sandbox/types/platform.proto) +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 860447de..d1bc65f9 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -85,10 +85,8 @@ target_link_libraries(libisula_client libisulad_tools) + if (GRPC_CONNECTOR) + target_link_libraries(libisula_client -Wl,--as-needed -lstdc++) + target_link_libraries(libisula_client -Wl,--as-needed ${PROTOBUF_LIBRARY}) +- target_link_libraries(libisula_client -Wl,--no-as-needed ${GRPC_PP_REFLECTION_LIBRARY} ${GRPC_PP_LIBRARY} ${GRPC_LIBRARY} ${GPR_LIBRARY}) +- if(ABSL_SYNC_LIB) +- target_link_libraries(libisula_client -Wl,--no-as-needed ${ABSL_SYNC_LIB}) +- endif() ++ target_link_libraries(libisula_client -Wl,--as-needed ${GRPC_PP_REFLECTION_LIBRARY} ${GRPC_PP_LIBRARY} ${GRPC_LIBRARY} ${GPR_LIBRARY}) ++ target_link_libraries(libisula_client -Wl,--as-needed ${ISULAD_ABSL_USED_TARGETS}) + else() + target_link_libraries(libisula_client -ldl libhttpclient) + set_target_properties(libisula_client PROPERTIES LINKER_LANGUAGE "C") +@@ -182,13 +180,11 @@ endif() + if (GRPC_CONNECTOR) + target_link_libraries(isulad -Wl,--as-needed -lstdc++) + target_link_libraries(isulad -Wl,--as-needed ${WEBSOCKET_LIBRARY} ${PROTOBUF_LIBRARY}) +- target_link_libraries(isulad -Wl,--no-as-needed ${GRPC_PP_REFLECTION_LIBRARY} ${GRPC_PP_LIBRARY} ${GRPC_LIBRARY} ${GPR_LIBRARY}) ++ target_link_libraries(isulad -Wl,--as-needed ${GRPC_PP_REFLECTION_LIBRARY} ${GRPC_PP_LIBRARY} ${GRPC_LIBRARY} ${GPR_LIBRARY}) + if (ENABLE_METRICS) + target_link_libraries(isulad ${EVHTP_LIBRARY} ${EVENT_LIBRARY}) + endif() +- if(ABSL_SYNC_LIB) +- target_link_libraries(isulad -Wl,--no-as-needed ${ABSL_SYNC_LIB}) +- endif() ++ target_link_libraries(isulad -Wl,--as-needed ${ISULAD_ABSL_USED_TARGETS}) + else() + message("Restful iSulad") + target_link_libraries(isulad ${EVHTP_LIBRARY} ${EVENT_LIBRARY}) +diff --git a/test/sandbox/controller/manager/CMakeLists.txt b/test/sandbox/controller/manager/CMakeLists.txt +index 3724538e..6e8c9052 100644 +--- a/test/sandbox/controller/manager/CMakeLists.txt ++++ b/test/sandbox/controller/manager/CMakeLists.txt +@@ -40,8 +40,6 @@ target_include_directories(${EXE} PUBLIC + ) + + target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${ISULA_LIBUTILS_LIBRARY} libutils_ut -lgrpc -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) +-if(ABSL_SYNC_LIB) +- target_link_libraries(${EXE} -Wl,--no-as-needed ${ABSL_SYNC_LIB}) +-endif() ++target_link_libraries(${EXE} -Wl,--as-needed ${ISULAD_ABSL_USED_TARGETS}) + add_test(NAME ${EXE} COMMAND ${EXE} --gtest_output=xml:${EXE}-Results.xml) + set_tests_properties(${EXE} PROPERTIES TIMEOUT 120) +diff --git a/test/sandbox/controller/sandboxer/async_wait_call/CMakeLists.txt b/test/sandbox/controller/sandboxer/async_wait_call/CMakeLists.txt +index c8eb803e..0631988a 100644 +--- a/test/sandbox/controller/sandboxer/async_wait_call/CMakeLists.txt ++++ b/test/sandbox/controller/sandboxer/async_wait_call/CMakeLists.txt +@@ -32,8 +32,6 @@ target_include_directories(${EXE} PUBLIC + ) + + target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${ISULA_LIBUTILS_LIBRARY} libutils_ut -lgrpc -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) +-if(ABSL_SYNC_LIB) +- target_link_libraries(${EXE} -Wl,--no-as-needed ${ABSL_SYNC_LIB}) +-endif() ++target_link_libraries(${EXE} -Wl,--as-needed ${ISULAD_ABSL_USED_TARGETS}) + add_test(NAME ${EXE} COMMAND ${EXE} --gtest_output=xml:${EXE}-Results.xml) + set_tests_properties(${EXE} PROPERTIES TIMEOUT 120) +diff --git a/test/sandbox/controller/sandboxer/sandboxer_client/CMakeLists.txt b/test/sandbox/controller/sandboxer/sandboxer_client/CMakeLists.txt +index 91f26883..881797c6 100644 +--- a/test/sandbox/controller/sandboxer/sandboxer_client/CMakeLists.txt ++++ b/test/sandbox/controller/sandboxer/sandboxer_client/CMakeLists.txt +@@ -36,8 +36,6 @@ target_include_directories(${EXE} PUBLIC + ) + + target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${ISULA_LIBUTILS_LIBRARY} libutils_ut -lgrpc -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) +-if(ABSL_SYNC_LIB) +- target_link_libraries(${EXE} -Wl,--no-as-needed ${ABSL_SYNC_LIB}) +-endif() ++target_link_libraries(${EXE} -Wl,--as-needed ${ISULAD_ABSL_USED_TARGETS}) + add_test(NAME ${EXE} COMMAND ${EXE} --gtest_output=xml:${EXE}-Results.xml) + set_tests_properties(${EXE} PROPERTIES TIMEOUT 120) +diff --git a/test/sandbox/controller/sandboxer/sandboxer_controller/CMakeLists.txt b/test/sandbox/controller/sandboxer/sandboxer_controller/CMakeLists.txt +index d38392e0..963ce9a5 100644 +--- a/test/sandbox/controller/sandboxer/sandboxer_controller/CMakeLists.txt ++++ b/test/sandbox/controller/sandboxer/sandboxer_controller/CMakeLists.txt +@@ -33,8 +33,6 @@ target_include_directories(${EXE} PUBLIC + ) + + target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${ISULA_LIBUTILS_LIBRARY} libutils_ut -lgrpc -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) +-if(ABSL_SYNC_LIB) +- target_link_libraries(${EXE} -Wl,--no-as-needed ${ABSL_SYNC_LIB}) +-endif() ++target_link_libraries(${EXE} -Wl,--as-needed ${ISULAD_ABSL_USED_TARGETS}) + add_test(NAME ${EXE} COMMAND ${EXE} --gtest_output=xml:${EXE}-Results.xml) + set_tests_properties(${EXE} PROPERTIES TIMEOUT 120) +diff --git a/test/sandbox/controller/shim/CMakeLists.txt b/test/sandbox/controller/shim/CMakeLists.txt +index af066546..6423bb80 100644 +--- a/test/sandbox/controller/shim/CMakeLists.txt ++++ b/test/sandbox/controller/shim/CMakeLists.txt +@@ -50,8 +50,6 @@ target_include_directories(${EXE} PUBLIC + ) + + target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${ISULA_LIBUTILS_LIBRARY} libutils_ut -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) +-if(ABSL_SYNC_LIB) +- target_link_libraries(${EXE} -Wl,--no-as-needed ${ABSL_SYNC_LIB}) +-endif() ++target_link_libraries(${EXE} -Wl,--as-needed ${ISULAD_ABSL_USED_TARGETS}) + add_test(NAME ${EXE} COMMAND ${EXE} --gtest_output=xml:${EXE}-Results.xml) + set_tests_properties(${EXE} PROPERTIES TIMEOUT 120) +diff --git a/test/sandbox/sandbox/CMakeLists.txt b/test/sandbox/sandbox/CMakeLists.txt +index efcc2bdc..138d4d8d 100644 +--- a/test/sandbox/sandbox/CMakeLists.txt ++++ b/test/sandbox/sandbox/CMakeLists.txt +@@ -48,8 +48,6 @@ target_include_directories(${EXE} PUBLIC + ) + + target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${ISULA_LIBUTILS_LIBRARY} libutils_ut -lgrpc -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) +-if(ABSL_SYNC_LIB) +- target_link_libraries(${EXE} -Wl,--no-as-needed ${ABSL_SYNC_LIB}) +-endif() ++target_link_libraries(${EXE} -Wl,--as-needed ${ISULAD_ABSL_USED_TARGETS}) + add_test(NAME ${EXE} COMMAND ${EXE} --gtest_output=xml:${EXE}-Results.xml) + set_tests_properties(${EXE} PROPERTIES TIMEOUT 120) +diff --git a/test/sandbox/sandbox_manager/CMakeLists.txt b/test/sandbox/sandbox_manager/CMakeLists.txt +index f43b0f97..5a7cb2ea 100644 +--- a/test/sandbox/sandbox_manager/CMakeLists.txt ++++ b/test/sandbox/sandbox_manager/CMakeLists.txt +@@ -48,8 +48,6 @@ target_include_directories(${EXE} PUBLIC + ) + set_target_properties(${EXE} PROPERTIES LINK_FLAGS "-Wl,--wrap,util_list_all_subdir") + target_link_libraries(${EXE} ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY} ${GMOCK_MAIN_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${ISULA_LIBUTILS_LIBRARY} libutils_ut -lgrpc -lgrpc++ -lprotobuf -lcrypto -lyajl -lz) +-if(ABSL_SYNC_LIB) +- target_link_libraries(${EXE} -Wl,--no-as-needed ${ABSL_SYNC_LIB}) +-endif() ++target_link_libraries(${EXE} -Wl,--as-needed ${ISULAD_ABSL_USED_TARGETS}) + add_test(NAME ${EXE} COMMAND ${EXE} --gtest_output=xml:${EXE}-Results.xml) + set_tests_properties(${EXE} PROPERTIES TIMEOUT 120) +-- +2.25.1 + 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 deleted file mode 100644 index 97a3302..0000000 --- a/0002-sandbox-adapt-UT-when-del-m_containers-and-m_contain.patch +++ /dev/null @@ -1,167 +0,0 @@ -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 deleted file mode 100644 index 072a5e5..0000000 --- a/0003-Add-Readonly-Masked-Path-and-RunAsGroup-support-for-.patch +++ /dev/null @@ -1,642 +0,0 @@ -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/0003-bugfix-for-mount-point-remains-under-special-circums.patch b/0003-bugfix-for-mount-point-remains-under-special-circums.patch new file mode 100644 index 0000000..c9e2442 --- /dev/null +++ b/0003-bugfix-for-mount-point-remains-under-special-circums.patch @@ -0,0 +1,123 @@ +From cd018d3c1ebff2a328912d99fc43c9a7e4f60704 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Thu, 25 Jan 2024 11:24:59 +0800 +Subject: [PATCH 3/6] bugfix for mount point remains under special + circumstances + +Signed-off-by: zhongtao +--- + src/cmd/isulad/main.c | 14 +++++++------- + .../modules/container/leftover_cleanup/cleanup.c | 14 +++++++------- + src/utils/tar/util_archive.c | 14 +++++++------- + 3 files changed, 21 insertions(+), 21 deletions(-) + +diff --git a/src/cmd/isulad/main.c b/src/cmd/isulad/main.c +index d9d8afa0..deca72be 100644 +--- a/src/cmd/isulad/main.c ++++ b/src/cmd/isulad/main.c +@@ -1271,23 +1271,23 @@ static int do_ensure_isulad_tmpdir_security(const char *isulad_tmp_dir) + char tmp_dir[PATH_MAX] = { 0 }; + char cleanpath[PATH_MAX] = { 0 }; + +- nret = snprintf(tmp_dir, PATH_MAX, "%s/isulad_tmpdir", isulad_tmp_dir); +- if (nret < 0 || (size_t)nret >= PATH_MAX) { +- ERROR("Failed to snprintf"); ++ if (realpath(isulad_tmp_dir, cleanpath) == NULL) { ++ ERROR("Failed to get real path for %s", tmp_dir); + return -1; + } + +- if (util_clean_path(tmp_dir, cleanpath, sizeof(cleanpath)) == NULL) { +- ERROR("Failed to clean path for %s", tmp_dir); ++ nret = snprintf(tmp_dir, PATH_MAX, "%s/isulad_tmpdir", cleanpath); ++ if (nret < 0 || (size_t)nret >= PATH_MAX) { ++ ERROR("Failed to snprintf"); + return -1; + } + +- if (isulad_tmpdir_security_check(cleanpath) == 0) { ++ if (isulad_tmpdir_security_check(tmp_dir) == 0) { + return 0; + } + + INFO("iSulad tmpdir: %s does not meet security requirements, recreate it", isulad_tmp_dir); +- return recreate_tmpdir(cleanpath); ++ return recreate_tmpdir(tmp_dir); + } + + static int ensure_isulad_tmpdir_security() +diff --git a/src/daemon/modules/container/leftover_cleanup/cleanup.c b/src/daemon/modules/container/leftover_cleanup/cleanup.c +index b78a4d15..08151f42 100644 +--- a/src/daemon/modules/container/leftover_cleanup/cleanup.c ++++ b/src/daemon/modules/container/leftover_cleanup/cleanup.c +@@ -175,22 +175,22 @@ static void cleanup_path(char *dir) + char tmp_dir[PATH_MAX] = { 0 }; + char cleanpath[PATH_MAX] = { 0 }; + +- nret = snprintf(tmp_dir, PATH_MAX, "%s/isulad_tmpdir", dir); +- if (nret < 0 || (size_t)nret >= PATH_MAX) { +- ERROR("Failed to snprintf"); ++ if (realpath(dir, cleanpath) == NULL) { ++ ERROR("get real path for %s failed", tmp_dir); + return; + } + +- if (util_clean_path(tmp_dir, cleanpath, sizeof(cleanpath)) == NULL) { +- ERROR("clean path for %s failed", tmp_dir); ++ nret = snprintf(tmp_dir, PATH_MAX, "%s/isulad_tmpdir", cleanpath); ++ if (nret < 0 || (size_t)nret >= PATH_MAX) { ++ ERROR("Failed to snprintf"); + return; + } + +- if (!util_dir_exists(cleanpath)) { ++ if (!util_dir_exists(tmp_dir)) { + return; + } + +- nret = util_scan_subdirs(cleanpath, walk_isulad_tmpdir_cb, NULL); ++ nret = util_scan_subdirs(tmp_dir, walk_isulad_tmpdir_cb, NULL); + if (nret != 0) { + ERROR("failed to scan isulad tmp subdirs"); + } +diff --git a/src/utils/tar/util_archive.c b/src/utils/tar/util_archive.c +index 0a7309c9..e4c302bc 100644 +--- a/src/utils/tar/util_archive.c ++++ b/src/utils/tar/util_archive.c +@@ -218,18 +218,18 @@ static int make_safedir_is_noexec(const char *flock_path, const char *dstdir, ch + isulad_tmpdir_env = DEFAULT_ISULAD_TMPDIR; + } + +- nret = snprintf(isula_tmpdir, PATH_MAX, "%s/isulad_tmpdir", isulad_tmpdir_env); +- if (nret < 0 || (size_t)nret >= PATH_MAX) { +- ERROR("Failed to snprintf"); ++ if (realpath(isulad_tmpdir_env, cleanpath) == NULL) { ++ ERROR("Failed to get real path for %s", isula_tmpdir); + return -1; + } + +- if (util_clean_path(isula_tmpdir, cleanpath, sizeof(cleanpath)) == NULL) { +- ERROR("clean path for %s failed", isula_tmpdir); ++ nret = snprintf(isula_tmpdir, PATH_MAX, "%s/isulad_tmpdir", cleanpath); ++ if (nret < 0 || (size_t)nret >= PATH_MAX) { ++ ERROR("Failed to snprintf"); + return -1; + } + +- nret = snprintf(tmp_dir, PATH_MAX, "%s/tar-chroot-XXXXXX", cleanpath); ++ nret = snprintf(tmp_dir, PATH_MAX, "%s/tar-chroot-XXXXXX", isula_tmpdir); + if (nret < 0 || (size_t)nret >= PATH_MAX) { + ERROR("Failed to snprintf string"); + return -1; +@@ -247,7 +247,7 @@ static int make_safedir_is_noexec(const char *flock_path, const char *dstdir, ch + } + + // ensure parent dir is exist +- if (util_mkdir_p(cleanpath, ISULAD_TEMP_DIRECTORY_MODE) != 0) { ++ if (util_mkdir_p(isula_tmpdir, ISULAD_TEMP_DIRECTORY_MODE) != 0) { + return -1; + } + +-- +2.25.1 + diff --git a/0004-do-not-cleanup-if-the-directory-does-not-exist.patch b/0004-do-not-cleanup-if-the-directory-does-not-exist.patch new file mode 100644 index 0000000..e9feb7a --- /dev/null +++ b/0004-do-not-cleanup-if-the-directory-does-not-exist.patch @@ -0,0 +1,71 @@ +From 7f13d95572040d30b70edbfac3c4b7350ee8855c Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Fri, 26 Jan 2024 12:59:45 +0800 +Subject: [PATCH 4/6] do not cleanup if the directory does not exist + +Signed-off-by: zhongtao +--- + src/cmd/isulad/main.c | 20 ++++++++++++++++++- + .../container/leftover_cleanup/cleanup.c | 13 +++++++++++- + 2 files changed, 31 insertions(+), 2 deletions(-) + +diff --git a/src/cmd/isulad/main.c b/src/cmd/isulad/main.c +index deca72be..fd0b6e89 100644 +--- a/src/cmd/isulad/main.c ++++ b/src/cmd/isulad/main.c +@@ -1270,8 +1270,26 @@ static int do_ensure_isulad_tmpdir_security(const char *isulad_tmp_dir) + int nret; + char tmp_dir[PATH_MAX] = { 0 }; + char cleanpath[PATH_MAX] = { 0 }; ++ char isulad_tmp_cleanpath[PATH_MAX] = { 0 }; + +- if (realpath(isulad_tmp_dir, cleanpath) == NULL) { ++ if (util_clean_path(isulad_tmp_dir, isulad_tmp_cleanpath, sizeof(isulad_tmp_cleanpath)) == NULL) { ++ ERROR("Failed to clean path for %s", isulad_tmp_dir); ++ return -1; ++ } ++ ++ // Determine whether isulad_tmp_dir exists. If it does not exist, create it ++ // to prevent realpath from reporting errors because the folder does not exist. ++ if (!util_dir_exists(isulad_tmp_cleanpath)) { ++ nret = snprintf(tmp_dir, PATH_MAX, "%s/isulad_tmpdir", isulad_tmp_cleanpath); ++ if (nret < 0 || (size_t)nret >= PATH_MAX) { ++ ERROR("Failed to snprintf"); ++ return -1; ++ } ++ INFO("iSulad tmpdir: %s does not exist, create it", isulad_tmp_dir); ++ return recreate_tmpdir(tmp_dir); ++ } ++ ++ if (realpath(isulad_tmp_cleanpath, cleanpath) == NULL) { + ERROR("Failed to get real path for %s", tmp_dir); + return -1; + } +diff --git a/src/daemon/modules/container/leftover_cleanup/cleanup.c b/src/daemon/modules/container/leftover_cleanup/cleanup.c +index 08151f42..16dba630 100644 +--- a/src/daemon/modules/container/leftover_cleanup/cleanup.c ++++ b/src/daemon/modules/container/leftover_cleanup/cleanup.c +@@ -174,8 +174,19 @@ static void cleanup_path(char *dir) + int nret; + char tmp_dir[PATH_MAX] = { 0 }; + char cleanpath[PATH_MAX] = { 0 }; ++ char dir_cleanpath[PATH_MAX] = { 0 }; + +- if (realpath(dir, cleanpath) == NULL) { ++ if (util_clean_path(dir, dir_cleanpath, sizeof(dir_cleanpath)) == NULL) { ++ ERROR("clean path for %s failed", dir); ++ return; ++ } ++ ++ // If dir does not exist, skip cleanup ++ if (!util_dir_exists(dir_cleanpath)) { ++ return; ++ } ++ ++ if (realpath(dir_cleanpath, cleanpath) == NULL) { + ERROR("get real path for %s failed", tmp_dir); + return; + } +-- +2.25.1 + diff --git a/0004-network-support-version-opt.patch b/0004-network-support-version-opt.patch deleted file mode 100644 index db3a845..0000000 --- a/0004-network-support-version-opt.patch +++ /dev/null @@ -1,482 +0,0 @@ -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 deleted file mode 100644 index 39ebd5a..0000000 --- a/0005-doc-support-version-opt.patch +++ /dev/null @@ -1,87 +0,0 @@ -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/0005-module-only-deletes-the-temporary-files-it-creates.patch b/0005-module-only-deletes-the-temporary-files-it-creates.patch new file mode 100644 index 0000000..bc0b096 --- /dev/null +++ b/0005-module-only-deletes-the-temporary-files-it-creates.patch @@ -0,0 +1,151 @@ +From 69dcd191afbdea5a178fb96a21e28537c2fc6a75 Mon Sep 17 00:00:00 2001 +From: zhongtao +Date: Sat, 27 Jan 2024 11:16:37 +0800 +Subject: [PATCH 5/6] module only deletes the temporary files it creates + +Signed-off-by: zhongtao +--- + src/cmd/isulad/main.c | 2 +- + src/common/constants.h | 2 +- + src/daemon/modules/image/oci/oci_image.c | 44 +++++++++++++++++-- + src/daemon/modules/image/oci/oci_image.h | 4 ++ + src/daemon/modules/image/oci/oci_load.c | 2 +- + .../modules/image/oci/registry/registry.c | 2 +- + 6 files changed, 48 insertions(+), 8 deletions(-) + +diff --git a/src/cmd/isulad/main.c b/src/cmd/isulad/main.c +index fd0b6e89..7c0c072e 100644 +--- a/src/cmd/isulad/main.c ++++ b/src/cmd/isulad/main.c +@@ -1252,7 +1252,7 @@ static int isulad_tmpdir_security_check(const char *tmp_dir) + + static int recreate_tmpdir(const char *tmp_dir) + { +- if (util_recursive_rmdir(tmp_dir, 0) != 0) { ++ if (util_path_remove(tmp_dir) != 0) { + ERROR("Failed to remove directory %s", tmp_dir); + return -1; + } +diff --git a/src/common/constants.h b/src/common/constants.h +index 27d4956e..8a6f86d8 100644 +--- a/src/common/constants.h ++++ b/src/common/constants.h +@@ -50,7 +50,7 @@ extern "C" { + + #define TEMP_DIRECTORY_MODE 0700 + +-#define ISULAD_TEMP_DIRECTORY_MODE 0600 ++#define ISULAD_TEMP_DIRECTORY_MODE 0700 + + #define CONSOLE_FIFO_DIRECTORY_MODE 0770 + +diff --git a/src/daemon/modules/image/oci/oci_image.c b/src/daemon/modules/image/oci/oci_image.c +index 9cf2cd4f..ce1c8a6b 100644 +--- a/src/daemon/modules/image/oci/oci_image.c ++++ b/src/daemon/modules/image/oci/oci_image.c +@@ -283,10 +283,42 @@ out: + return ret; + } + ++// remove dir that image module created ++// return false when failed to rmdir ++// eg: oci-image-load-XXXXXX && registry-XXXXXX ++static bool remove_image_tmpdir_cb(const char *path_name, const struct dirent *sub_dir, void *context) ++{ ++ int nret = 0; ++ char tmpdir[PATH_MAX] = { 0 }; ++ ++ if (sub_dir == NULL) { ++ return true; ++ } ++ ++ if (!util_has_prefix(sub_dir->d_name, LOAD_TMPDIR_PREFIX) && !util_has_prefix(sub_dir->d_name, REGISTRY_TMPDIR_PREFIX)) { ++ // only remove directory that image module created ++ return true; ++ } ++ ++ nret = snprintf(tmpdir, PATH_MAX, "%s/%s", path_name, sub_dir->d_name); ++ if (nret < 0 || (size_t)nret >= PATH_MAX) { ++ ERROR("Failed to snprintf for %s", sub_dir->d_name); ++ return false; ++ } ++ ++ if (util_recursive_rmdir(tmpdir, 0) != 0) { ++ ERROR("Failed to remove path %s", tmpdir); ++ return false; ++ } ++ ++ return true; ++} ++ + static int recreate_image_tmpdir() + { + char *image_tmp_path = NULL; + int ret = 0; ++ int nret = 0; + + image_tmp_path = oci_get_isulad_tmpdir(g_oci_image_module_data.root_dir); + if (image_tmp_path == NULL) { +@@ -295,10 +327,14 @@ static int recreate_image_tmpdir() + goto out; + } + +- if (util_recursive_rmdir(image_tmp_path, 0)) { +- ERROR("failed to remove directory %s", image_tmp_path); +- ret = -1; +- goto out; ++ // If image_tmp_path exist, cleanup it ++ if (util_dir_exists(image_tmp_path)) { ++ nret = util_scan_subdirs(image_tmp_path, remove_image_tmpdir_cb, NULL); ++ if (nret != 0) { ++ ERROR("Failed to scan isulad tmp subdirs"); ++ ret = -1; ++ goto out; ++ } + } + + if (util_mkdir_p(image_tmp_path, TEMP_DIRECTORY_MODE)) { +diff --git a/src/daemon/modules/image/oci/oci_image.h b/src/daemon/modules/image/oci/oci_image.h +index c7304897..482091d6 100644 +--- a/src/daemon/modules/image/oci/oci_image.h ++++ b/src/daemon/modules/image/oci/oci_image.h +@@ -38,6 +38,10 @@ struct oci_image_module_data { + char **insecure_registries; + size_t insecure_registries_len; + }; ++ ++#define LOAD_TMPDIR_PREFIX "oci-image-load-" ++#define REGISTRY_TMPDIR_PREFIX "registry-" ++ + struct oci_image_module_data *get_oci_image_data(void); + + int oci_init(const isulad_daemon_configs *args); +diff --git a/src/daemon/modules/image/oci/oci_load.c b/src/daemon/modules/image/oci/oci_load.c +index 31ae3849..534e2647 100644 +--- a/src/daemon/modules/image/oci/oci_load.c ++++ b/src/daemon/modules/image/oci/oci_load.c +@@ -1048,7 +1048,7 @@ static char *oci_load_path_create() + goto out; + } + +- nret = snprintf(tmp_dir, PATH_MAX, "%s/oci-image-load-XXXXXX", image_tmp_path); ++ nret = snprintf(tmp_dir, PATH_MAX, "%s/%sXXXXXX", image_tmp_path, LOAD_TMPDIR_PREFIX); + if (nret < 0 || (size_t)nret >= sizeof(tmp_dir)) { + ERROR("Path is too long"); + ret = -1; +diff --git a/src/daemon/modules/image/oci/registry/registry.c b/src/daemon/modules/image/oci/registry/registry.c +index 751a8727..aed3057a 100644 +--- a/src/daemon/modules/image/oci/registry/registry.c ++++ b/src/daemon/modules/image/oci/registry/registry.c +@@ -1908,7 +1908,7 @@ static int prepare_pull_desc(pull_descriptor *desc, registry_pull_options *optio + goto out; + } + +- sret = snprintf(blobpath, PATH_MAX, "%s/registry-XXXXXX", image_tmp_path); ++ sret = snprintf(blobpath, PATH_MAX, "%s/%sXXXXXX", image_tmp_path, REGISTRY_TMPDIR_PREFIX); + if (sret < 0 || (size_t)sret >= PATH_MAX) { + ERROR("image tmp work path too long"); + ret = -1; +-- +2.25.1 + diff --git a/0006-2242-disable-grpc-remote-connect-by-default.patch b/0006-2242-disable-grpc-remote-connect-by-default.patch deleted file mode 100644 index 8fa1bb0..0000000 --- a/0006-2242-disable-grpc-remote-connect-by-default.patch +++ /dev/null @@ -1,26 +0,0 @@ -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/0006-skip-devmapper-ut.patch b/0006-skip-devmapper-ut.patch new file mode 100644 index 0000000..6374132 --- /dev/null +++ b/0006-skip-devmapper-ut.patch @@ -0,0 +1,26 @@ +From b290e7fb553c5cc6746c9dcfe4896098f74bc7d7 Mon Sep 17 00:00:00 2001 +From: jikai +Date: Tue, 30 Jan 2024 12:35:58 +0800 +Subject: [PATCH 6/6] skip devmapper ut + +Signed-off-by: jikai +--- + CI/make-and-install.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/CI/make-and-install.sh b/CI/make-and-install.sh +index c1d26ff1..9bb984cd 100755 +--- a/CI/make-and-install.sh ++++ b/CI/make-and-install.sh +@@ -75,7 +75,7 @@ mkdir build && cd build + cmake -DCMAKE_BUILD_TYPE=Debug -DENABLE_UT=ON -DENABLE_CRI_API_V1=ON -DENABLE_SHIM_V2=ON -DENABLE_METRICS=ON .. + make -j $(nproc) + make install +-ctest -T memcheck --output-on-failure ++ctest -E "driver_devmapper_ut" -T memcheck --output-on-failure + echo_success "===================RUN DT-LLT TESTCASES END=========================" + + # build fuzz +-- +2.25.1 + diff --git a/0007-2244-Save-task-address-of-shim-v2.patch b/0007-2244-Save-task-address-of-shim-v2.patch deleted file mode 100644 index c7bf391..0000000 --- a/0007-2244-Save-task-address-of-shim-v2.patch +++ /dev/null @@ -1,209 +0,0 @@ -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 deleted file mode 100644 index c1fc023..0000000 --- a/0008-2233-add-runc-append-function-design-doc.patch +++ /dev/null @@ -1,110 +0,0 @@ -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 deleted file mode 100644 index 116a30f..0000000 --- a/0009-2243-Refactor-capbilities-specs.patch +++ /dev/null @@ -1,1056 +0,0 @@ -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 deleted file mode 100644 index 8a7253e..0000000 --- a/0010-2245-fix-utils_verify_ut-failure-when-remote-grpc-fu.patch +++ /dev/null @@ -1,33 +0,0 @@ -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 deleted file mode 100644 index 088e339..0000000 --- a/0011-add-runc-attach-implement.patch +++ /dev/null @@ -1,1312 +0,0 @@ -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 deleted file mode 100644 index 401d89b..0000000 --- a/0012-add-runc-attach-implement-unit-test-and-ci-test.patch +++ /dev/null @@ -1,242 +0,0 @@ -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 deleted file mode 100644 index 14c4148..0000000 --- a/0013-support-gcov-of-CI.patch +++ /dev/null @@ -1,26 +0,0 @@ -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 deleted file mode 100644 index ff36bcc..0000000 --- a/0014-compatibility-for-manage-pods-which-created-by-old-i.patch +++ /dev/null @@ -1,163 +0,0 @@ -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 deleted file mode 100644 index 20223a6..0000000 --- a/0015-2250-Remove-PERFMON-BPF-CHECKPOINT_RESTORE.patch +++ /dev/null @@ -1,33 +0,0 @@ -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 deleted file mode 100644 index afc4d5e..0000000 --- a/0016-improve-event-logs.patch +++ /dev/null @@ -1,202 +0,0 @@ -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 deleted file mode 100644 index 0002444..0000000 --- a/0017-2251-open-ENABLE_GRPC_REMOTE_CONNECT-in-CI.patch +++ /dev/null @@ -1,57 +0,0 @@ -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 deleted file mode 100644 index 48d9f0c..0000000 --- a/0018-Add-compatibility-between-iSulad-and-k8s.patch +++ /dev/null @@ -1,57 +0,0 @@ -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 deleted file mode 100644 index c371d1a..0000000 --- a/0019-2254-lcr-container-with-a-damaged-config-file-will-r.patch +++ /dev/null @@ -1,384 +0,0 @@ -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 deleted file mode 100644 index bf00f1e..0000000 --- a/0020-2253-bugfix-for-runc-container-exec.patch +++ /dev/null @@ -1,39 +0,0 @@ -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 deleted file mode 100644 index 6d0ba03..0000000 --- a/0021-bugfix-of-update-restart-policy-for-auto-remove-cont.patch +++ /dev/null @@ -1,58 +0,0 @@ -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 deleted file mode 100644 index 1f324ae..0000000 --- a/0022-add-update-restart-policy-test.patch +++ /dev/null @@ -1,57 +0,0 @@ -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 deleted file mode 100644 index e5ce564..0000000 --- a/0023-2260-bugfix-for-rebuild-config.patch +++ /dev/null @@ -1,73 +0,0 @@ -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 deleted file mode 100644 index 534c2c5..0000000 --- a/0024-2170-isula-image-pull.patch +++ /dev/null @@ -1,1815 +0,0 @@ -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 deleted file mode 100644 index 0fe36f1..0000000 --- a/0025-2084-image-pull.patch +++ /dev/null @@ -1,84 +0,0 @@ -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 deleted file mode 100644 index de75868..0000000 --- a/0026-CI-add-ncurse-for-ubuntu-and-centos.patch +++ /dev/null @@ -1,39 +0,0 @@ -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 deleted file mode 100644 index 86b4eca..0000000 --- a/0027-improve-code-of-pull-progress.patch +++ /dev/null @@ -1,631 +0,0 @@ -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 deleted file mode 100644 index e1fb272..0000000 --- a/0028-2230-format-code.patch +++ /dev/null @@ -1,3476 +0,0 @@ -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 deleted file mode 100644 index 92f7b63..0000000 --- a/0029-2255-Fix-cpusets-offline-issue.patch +++ /dev/null @@ -1,445 +0,0 @@ -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 deleted file mode 100644 index dd09a65..0000000 --- a/0030-modify-daemon-json-default-runtime-to-runc.patch +++ /dev/null @@ -1,52 +0,0 @@ -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 deleted file mode 100644 index 9b8f8d8..0000000 --- a/0031-modify-CI-for-default-runtime-to-runc.patch +++ /dev/null @@ -1,815 +0,0 @@ -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 deleted file mode 100644 index e28c5fa..0000000 --- a/0032-add-ut-for-devicemapper.patch +++ /dev/null @@ -1,737 +0,0 @@ -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 deleted file mode 100644 index ec42563..0000000 --- a/0033-2275-bugfix-for-rt_lcr_rebuild_config.patch +++ /dev/null @@ -1,46 +0,0 @@ -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 deleted file mode 100644 index 1573b9e..0000000 --- a/0034-2277-remove-shim-v2-format-error-log.patch +++ /dev/null @@ -1,25 +0,0 @@ -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 deleted file mode 100644 index c870e52..0000000 --- a/0035-2276-bugfix-for-integration_check.sh.patch +++ /dev/null @@ -1,26 +0,0 @@ -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 deleted file mode 100644 index 40e9feb..0000000 --- a/0036-modify-create_network.sh-for-default-runtime-changed.patch +++ /dev/null @@ -1,40 +0,0 @@ -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 deleted file mode 100644 index 7ba3583..0000000 --- a/0037-modify-the-container-runtime-when-running-embedded.s.patch +++ /dev/null @@ -1,141 +0,0 @@ -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 deleted file mode 100644 index b77ff29..0000000 --- a/0038-save-sandbox-to-disk-after-network-ready.patch +++ /dev/null @@ -1,68 +0,0 @@ -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 deleted file mode 100644 index 0f878d4..0000000 --- a/0039-fix-the-problem-of-abnormal-branches-not-waiting-for.patch +++ /dev/null @@ -1,153 +0,0 @@ -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 deleted file mode 100644 index 9ace537..0000000 --- a/0040-remove-embedded-image-support-in-readme.patch +++ /dev/null @@ -1,62 +0,0 @@ -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 deleted file mode 100644 index 4e178e8..0000000 --- a/0041-Acquire-system-info-in-on-demand.patch +++ /dev/null @@ -1,392 +0,0 @@ -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 deleted file mode 100644 index 2c9f725..0000000 --- a/0042-2268-bugfix-for-the-bliko-zero-value-exception-when-.patch +++ /dev/null @@ -1,92 +0,0 @@ -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 deleted file mode 100644 index 26748eb..0000000 --- a/0043-move-variable-declaration-out-of-loop.patch +++ /dev/null @@ -1,34 +0,0 @@ -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 deleted file mode 100644 index 5fa3a05..0000000 --- a/0044-2289-check-protobuf-and-grpc-version-in-cmake-for-cr.patch +++ /dev/null @@ -1,40 +0,0 @@ -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 deleted file mode 100644 index ad87cba..0000000 --- a/0045-improve-ut-for-devicemapper.patch +++ /dev/null @@ -1,381 +0,0 @@ -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 deleted file mode 100644 index 3831382..0000000 --- a/0046-2292-bugfix-for-run.sh-and-add-build-notify-msg-for-.patch +++ /dev/null @@ -1,56 +0,0 @@ -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 deleted file mode 100644 index 661dc88..0000000 --- a/0047-2295-keep-the-service-status-unchanged-after-iSulad-.patch +++ /dev/null @@ -1,251 +0,0 @@ -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 deleted file mode 100644 index e1eb159..0000000 --- a/0048-modify-attach-socket-name.patch +++ /dev/null @@ -1,40 +0,0 @@ -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 deleted file mode 100644 index 4c90ed4..0000000 --- a/0049-2298-bugfix-for-hook_ignore_poststart_error-run-in-o.patch +++ /dev/null @@ -1,110 +0,0 @@ -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 deleted file mode 100644 index 8fccf01..0000000 --- a/0050-2304-remove-build-and-test-in-coverage.patch +++ /dev/null @@ -1,28 +0,0 @@ -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 deleted file mode 100644 index 87e528a..0000000 --- a/0051-2303-use-a-timeout-epoll-loop-to-ensure-complete-dat.patch +++ /dev/null @@ -1,197 +0,0 @@ -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 deleted file mode 100644 index cf0c729..0000000 --- a/0052-modify-the-default-value-of-ISULAD_TMPDIR-to-var-lib.patch +++ /dev/null @@ -1,170 +0,0 @@ -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 deleted file mode 100644 index 9876957..0000000 --- a/0053-prevent-the-parent-dir-from-being-bind-mounted-to-th.patch +++ /dev/null @@ -1,58 +0,0 @@ -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 deleted file mode 100644 index c783229..0000000 --- a/0054-2308-Remove-unused-header-file.patch +++ /dev/null @@ -1,25 +0,0 @@ -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 deleted file mode 100644 index 90caa48..0000000 --- a/0055-verify-the-mount-dir-first-and-then-create-tmpdir.patch +++ /dev/null @@ -1,43 +0,0 @@ -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 deleted file mode 100644 index f6e434c..0000000 --- a/0056-2300-Maintaining-a-uniform-code-style.patch +++ /dev/null @@ -1,26 +0,0 @@ -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 deleted file mode 100644 index 3845146..0000000 --- a/0057-2312-Add-Huawei-Cloud-CodeArts-compilation-script.patch +++ /dev/null @@ -1,36 +0,0 @@ -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 deleted file mode 100644 index 94072ce..0000000 --- a/0058-bugfix-del-redundant-code.patch +++ /dev/null @@ -1,26 +0,0 @@ -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 deleted file mode 100644 index e2c236e..0000000 --- a/0059-improve-code-of-pull.patch +++ /dev/null @@ -1,71 +0,0 @@ -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 deleted file mode 100644 index 3c1de53..0000000 --- a/0060-remove-var-in-coverage-and-fix-build-test-remove.patch +++ /dev/null @@ -1,30 +0,0 @@ -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 deleted file mode 100644 index 1c7326c..0000000 --- a/0061-2320-improve-CI-test.patch +++ /dev/null @@ -1,165 +0,0 @@ -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 deleted file mode 100644 index e56bbd7..0000000 --- a/0062-verify-name-and-digest-consistency.patch +++ /dev/null @@ -1,319 +0,0 @@ -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 deleted file mode 100644 index 0d8f427..0000000 --- a/0063-code-improve-for-oci_rmi.patch +++ /dev/null @@ -1,35 +0,0 @@ -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 deleted file mode 100644 index 19ef9cb..0000000 --- a/0064-bugfix-for-resort_image_names.patch +++ /dev/null @@ -1,26 +0,0 @@ -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 deleted file mode 100644 index ba38cc7..0000000 --- a/0065-fix-stopp-removes-cont-error-remove-inspect-error-lo.patch +++ /dev/null @@ -1,76 +0,0 @@ -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 deleted file mode 100644 index a730c39..0000000 --- a/0066-2313-use-lxc-5.X-in-CI-testcase.patch +++ /dev/null @@ -1,41 +0,0 @@ -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 deleted file mode 100644 index a67684f..0000000 --- a/0067-2329-modify-mount-dev-directory-for-lxc-5.X.patch +++ /dev/null @@ -1,27 +0,0 @@ -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 deleted file mode 100644 index 97aee02..0000000 --- a/0068-add-cri-1.29-api-change-docs.patch +++ /dev/null @@ -1,139 +0,0 @@ -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 deleted file mode 100644 index e57cee6..0000000 --- a/0069-add-exec-workdir-support-for-oci-runtime.patch +++ /dev/null @@ -1,57 +0,0 @@ -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 deleted file mode 100644 index 38687aa..0000000 --- a/0070-add-testcases-for-exec-workdir.patch +++ /dev/null @@ -1,27 +0,0 @@ -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 deleted file mode 100644 index 033dd14..0000000 --- a/0071-iSulad-restart-isuald-when-upgrade-active-isulad.patch +++ /dev/null @@ -1,34 +0,0 @@ -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 index 61cb1cb..bd96f53 100644 --- a/iSulad.spec +++ b/iSulad.spec @@ -1,5 +1,5 @@ -%global _version 2.1.4 -%global _release 5 +%global _version 2.1.5 +%global _release 1 %global is_systemd 1 %global enable_criv1 1 %global enable_shimv2 1 @@ -15,77 +15,12 @@ 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 +Patch0001: 0001-code-improve-for-sandbox.cc.patch +Patch0002: 0002-fix-compile-error-with-protobuf-25.1-and-grpc-1.60.x.patch +Patch0003: 0003-bugfix-for-mount-point-remains-under-special-circums.patch +Patch0004: 0004-do-not-cleanup-if-the-directory-does-not-exist.patch +Patch0005: 0005-module-only-deletes-the-temporary-files-it-creates.patch +Patch0006: 0006-skip-devmapper-ut.patch %ifarch x86_64 aarch64 Provides: libhttpclient.so()(64bit) @@ -113,8 +48,8 @@ Requires: sqlite BuildRequires: gtest-devel gmock-devel %endif -%define lcrver_lower 2.1.3-0 -%define lcrver_upper 2.1.4-0 +%define lcrver_lower 2.1.4-0 +%define lcrver_upper 2.1.5-0 BuildRequires: libisula-devel > %{lcrver_lower} libisula-devel < %{lcrver_upper} BuildRequires: cmake gcc-c++ yajl-devel @@ -341,6 +276,12 @@ fi %endif %changelog +* Tue Jan 30 2024 zhongtao - 2.1.5-1 +- Type: update +- ID: NA +- SUG: NA +- DESC: update to v2.1.5 + * Fri Dec 29 2023 yangjiaqi - 2.1.4-5 - Type: bugfix - ID: NA diff --git a/v2.1.4.tar.gz b/v2.1.5.tar.gz similarity index 61% rename from v2.1.4.tar.gz rename to v2.1.5.tar.gz index 38c66bc89ea580410e18ca490efe2eee49d1a965..d261c70a5e7e03426f542de82d519c78435b2e31 100644 GIT binary patch delta 10371348 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

J?!P>mUqM}+E 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
o<%oa90g#q=b zE-!Poq>1b>#}A`5lkB=kerAq?{c&j8$!UJ?&Lc7OaAx`(zhEAs%r08jq9!!U>)lgP z?+z`qWGZE22m_1;AYxr)2QGmFJNxG$w2X*QLKw*hO}$sHQtZd0X!z0k!*DgXPUw~g zoPqJt;@N)(E-Ms`TbL%Od&JSL@9m@aIp~wJ%dk<8h(_2duiWH`P>7NSoC~wJ#yCL_ zntHB}&pf*_GdXCFU&LsJS{0Ruf#Iss34TEpz3i#i!X=nvs`!w8%SpGR`@GhoUTKB& z5`1i>I9`>z$g#AjmoUD?bobH( z2_eh>js%J7#Dv9kxNu|Q0(4ihzt>+(Smy31(p|4B&fN>_4!iOj)eGuwK{mC#-3cb_ zw@zL}cPl(PF>m5(g%1;6Om_>j>E&K|q{M$B{rP}iU1N*t?)e*g^}2g)XxZp6LwGPmr~bbzsgT;X7Z%V^m%F0K0Qh)K(5Sw0VQv$3tpVZ#~u=?S%iPj z=&3K!2e#CUke;Z>E9^Wg!|A)cwb|3u6>;Qc=R0`)aeu1F|FI=$#had|56p+r*49!c z{|A3}=l=+|Vg8Sn8EY6NUVBs1gpNplfo=mQPbq#&Ryrs1*!Ipmp_lr@OX}<{H(J)fdZ_?J3;a8f8=j z3~h(9d76_>D;tYLGufPpiQ!EcOCBDj5m}LNknzjHRdu8g;q_SRse`8SKVHo%rcr*q?X@lG6} zZPR+Zcz5aB;+cn~#7bCph!t-J{(Wlx{DTE>-BKCX(YE$rwDmWO>vlIsrMqT=qmEs} zR9)4eu(b>dBN1Na%`SfwDxC3vY6MPU>?Y$+;VK#mMiCb}=4GXlR~vJdPPoM-fh~g8!@>5&(>he5%5CtsQ9Y4go@1EdP-V6l0k+uMwkWnpGt=&{ zzh?Z}>hMSBcl#^A7#&%&g*NY}=P5BGUFNK23lEo*)CHkLTU-dNo={-Tv@M!Yuo6}7 zfWM9EiTv_Bgi?Q2s3vI|#u*KUiCwJF#D&{}VVbxIi2=oLCKj5ha#E_8sYr`UE%^1$ zR5__K(#{kaUJ6A5>*;{MiyJ4_!Le;_j#6!IB`Uw*tLGVLIgu{X+7fJo&8Hou}}Z75J{GksG=akw1pcY9nr;dUl0mH4JdyZZ|;!a)`dgu!FKxEz$`h6 zzxgYcU&mj=;b5eJ%fc_J4$VaP?>c%*UmN6Cs;ipAhb^*6`u4JUyHd=eEcH@SZwerC z*>7U#|JMHAH80yz_S^haYyYLAq9xdV@w0&aw>i{YlK(r>8ftxQ|6PI43$_17OYOhW z-=zIF3_5>Kw4oVx^53pu$jAQs^t_$~e5v+dMqaqNIoJ~Y4eK;8%oa_j5kYfK{V0yp z5C1&-_o<~?bQy(_)@U%gI28Vx2(Z~@LFW)g=rHm4EG9;poC=|@!L#87ZIi|68*F%A zsvTIY_O{kwN8~q)ZMSWbHE^-otG7*-HSaPCTiSmk!Peg{3Vn|t7>7%==?c8HwzmYM z;omIY{Ei?PZF~el^yjn8+g#^mRS{@8t8%!FH>I#^OJ9V!btwkLh%hKdltD2f4T_QH zGbom`DvM!8BCfr65q8taQtYM?VK;48cGHNon?@El%rbIaV~gBsQT3PYkX=Ixci|2; zo2-8jNh^rZvQ&)`qO7Gm%7odzlo{)2XM+#@ZCmWzg+pOcO*DY>*U=)MIj@&t2BUJz zZtTD>ufh~6kfivwkQu405uX=bOS4OUSOjnBSb}8}E778Bk(Nz*BELM3!LO`V#N%vj zac%O8I=S$6OFo*lSPn0^HR3bX0gYF)K=Oox6Q3=HvRazQF_$Es!TuOa^g4c zVo0M)-OR$c3pIxEP}}u=(VHC9YY~6-WE;HKg-F`i+wbI4?fIXGfV!j; zzy;3#LXl9o}p{J-iPR zVI?gN4Uhn;KvlnMO0VfG^31TEi98xwnm1#leJQrEc3}%^R<^KqX$xzAE?Zbx+W^yI z6xQ2s_}Yf=xn5Okxa_$eLGlzuG5`Wk6}iBKyc)r!+(tM&tny@&%o#!j@kWoiEIuNdDc zr^Z^v@M{>0+?sBHfWHMjZs|A!;5?SCuqdBfnG3$vHTi`Rw&_T}4~ zC@2^P`ojbnw@=JWVg}ISH&178OxZUs&P@JDvA!@P@slTX?sCbV`hgNDa9Uk>)|<=5 zsR{e5(ReP&Ux)6YpYGIAPX3L5G0!-^FNG*mHPl;7+(6%F?@im^0vJ=kP|R3A#$B8I zLDHkaQ8BRl`Qb79=mmTDN%8F6Og!0@$WYAvF1oscwWiM6_YU)W=Y@S^48X$rm_3#9 z7|%TU+7-3GE0d*knSAEdAIs8U-!SGcoVG_E2Esw3IB|+CIq^&yxE+>%M$hg;7xC%z z!mY=MoXjeqNy3y#W;$W)kEIHx0Zb1FwHs4^77g^7X=A_yAQL7g z1^X}6odG+s0lT@%pc*uGr;~YX?d^kkGe~_T)A`nB?#Ag=WN(uF%Aedfwu(=yXjW8w zGw`{{YmRfgcKas!<-tl9VA-hmdDxXU2Ppk~cP5ka;*ts^(;&X&YpZRrLF8M932ktY zRZpYCek7>Ix>OQ>hpmW`xeBhlIK5%I#QfMJcZ&~4iiakO=N}?3;9x_X#QMkcz!dE9 zC%|=T^JcC;nX!U>okl+13p-XmpR057Zc`!q?x~rnli_g4zH@%|=O6Ix$OZf4iP^`0 z=l*N$U;e=~+++{koh@?A_f+ek6HVSbfLeSLP_%a5-+JNv}WfMAw0W0gdKja zEtr@o3U|AiXXBWcUM9IOUjI998wYx5vILi=M~KFM@ozC2=J4?RrK7MwQ?!qvshI}B zRK&EaHch55sE$)JIITb7jMj)8QXz7sXhGvOjc#`O0f&lZR6JJfig6F9nEz(lzWyy{tRfV9aD_B~3=0MGi;;&5<#Zp!Wk#i)l}Ru#`|uHp z7Lxy}mH(}SR^IHV*xr!s64d{TyDGuu#5s1Jln#g!>Y@ZSjRv$ZoD`cw4A7G0ITA3Ta z+t?UOr5b=U5g;fGh&yiAAK5p~HOxG^iW4s3IJ}H;du2j|wzFt>UpU)RCwu z0z!076!P!K7ZIv@qa3N=I}fe69x=jPkJOM2_xz5XMMM$AG^2pxuSWgmn-f{;>k!l| zb#-|5*dx%Cu%C%XbN5gpWof{FnSb}lL=P&Wujr)H5I2!YhU2lTQ3th(95tLO8I6sJ zSh_a_YLllv-)Cn0l&=irGT$VWmI?)OXq{e zu0Hc1R4l+i53)RGq%$BN=CT>s>AMSPcuuBLB-Ir9F%~-6!^1v?J04VQ#3H>tvNc<~mdp|EoC)ipt%=+revER|nfQLPtc&f-?Rb&*qIHWXhTpm8e3_D&u4(0XH#ZB z8Y-c{e_Lv==qaSh9L{#&?U{t}NhX;F38KL;4)^2s!w+>%Ath{gX}NLoq! z{w5XbkELM?pk6XPstW8^J;~kzn}P9c*0h2+h)B@bw%^QuVV1o0wDj;{G-zx}1MEE@ zF5qLbj6ppzxbBU^))WZ*Yw!gA2sG8hwy%}xbOxRVsA8$)r_^TyB{M^7bRvmf)0x~s zG>C&}M0V?R(g#GuT`CiYiA^v9+|^S_EAMF|n=14s(^|bZ0Xl5B3#xUN>qcaCbDG9l z-N|$p9%Ng8oqEe9MF|R5`L2`+Sa26WX%HUw=KHYd4l`fKrP)Z|Y2^4<2<1Gh5RaRd z)d0d=x)Hrs@L>-SXd!0?>YD;+f+PH9a$Nvb7vi`JM`YEq{fh17a>UZA#ZT)Mi1Io5 z8Fb~{prc*AbW(R`6S%%A%vC&-O7W@A@(!^;J&Qqq`UAI)l0^e00C;@j;ZK7|7oz)~ zLaHp7`CP$tLD~~bS*8Z&n+PYJap-_j%4(VsGf@W6wF#!-Y=-y&epQlRDwZ}SwRU)Sm&_>Y6`B#j5O4N3fNgPLF*?&2-4UGc9=6k=gD`X zN+B_Spfeb59Q%{4tK%dc7(drtu%3I8q+Ec1LW1~WGzVeUSm<}84163mn7iZIF2YIz zM!yLoP9_2%S!Mf-UF!p@*4FY_)w->l=7+{+pNtpJ4WswNv+Kn}6MRRgF0ktDTELYV zi}!IEc(U$qY?l!s@qYOS8q6-={yea1eXafM$?Vyie0ruTY^W7Mq38kHbsl_YKR#=J zkKDC~Zrk?;`(s%swXrsB9>~L&wIHLec^i7hzw4ks{QKF~%x4?q_YY0$GZ?^n{IL<* z7k@Y6U*m0g3Iv#ll+we3NQve1Fj|mwGFcucA))y7*vym5j&)h0XPrck=lS|twpa?= z?vpRkGe*|t#t1X^@KO85utL?w+WEnML3?-#zP|G}fnbT(3s~>-oKcLi~0T1fM7Wo5SYz0h+rvHq8H^b63oR_ViKVz!wRBx?K23pJ#{1;;B<}&+gKGf=aw0wRje+<|ZB#zd8Bu z#~0No?2#+>trPa>Ir2Gr3O$0Hpm$w7Hi$=Jl#><8z}w=fuRPCrqk$oKHF3QmKFN{| zT`Ez(xmmrG-mFLU)(gy^eMX)|Sd8yu*n^K@jKz`DI2ZIJgr|Zx?#(@axXHiguY4O? zX=Pg>pB=J1=$XHC)IL43JfrZ}rz=c8Z{6Hg@%zEz)ti+8LG{@K3n|c4t7^U3LCEpr zS-DI=5R=zz@6TWPj(n;vDFL4`#!g4h$vjom?&o4f`}CNkpHXNW-X;^XcaHIz<0hpj zFY0UZ1Np1rsAO@`Q!)#GUqLE|hV&)8JhQf(+O7w+Gt(zMNM%;EAZoeTuO79_te-0E zvYN*@&@r?iUa8{J(aP0dHddEYncf_g~&}JqFS~gzkFWp3ny6m9KALgTy@|95lB2p9zzpnQzm?va#-DDw$8>fj01D zKK!)oJLikz|KyttajgtGhn+eHvI5TFr3cK%p-cNXiYx4YlnAIzW-ZWjLEwOYlhAcK z*^P$m-a;|~PZB12>l^evmP*DfQ}jnJz~9ba7!qTo=Fltkn~9QgLl0-B&+$*5W+15I znTg`)Awmaw(;vTWpFTNzY0@6LudaX~G0-)Az7qz-$vSfWVAf2SJ%+d)#<#(O!C=6- z23B7$fOwOCo(UySJVO;v+||Nbp9e@Xf^EZ0bfIY<-o216fc{9(>dK)zUO#Jl$=)|f zQh0+-{Wlyi;{}@d?YT@o6VIe*>fhh6W9O!ATLS^{MMwi=tzhL(X!wLwz?)hxh(jV* zoQKP|H7aI;vB!@nN|<~4HEMGt_5!@`n>mYb1Hu%4oqfRGf%eoXF%MF9vG68FI&Q8{ z#?b2`uqqqN<&*JbHU_dM4Yxa&O!S(b7l4mmz=xpWE~}8uW^$lwcJ1eGON)yaT~a

    sVo7FM$>gQnj9zLVn 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 z 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 z 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⁣c%NDFI`k076gk0aH61J_yn_3=;$d(kDwav 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%0D%saq+niQGt}; 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�FW+{l2IEEGbh4 zwp{7I3bHnVX)Sx?)s=NZ7Mqp7@T6DM+>4aN-%hBytX@CE*P4SthK$={WcN9b=}@3A zJKSw*fA!SDk$}FWc_G~-0v1!$pxcv45EfVaqfqh~^NhozRVi`;uvy#n&5f9O*4lQm z&&3zyl(kd+c-<|Lp=Im^G1+`nvxxFpV?GTxCmJHO|GTUDFUqyqf>swXy&3tDL8x_D zjh(I}a-W46t0)MT*3uR{z|4YJwdcm%Be?OPfAF!2)){X7V2#ls%&Tj`r|Za^_tV~D zQgKN@RtSGe4rI3PcvCS-={u_uFNY9dFF%C*5q!6UYQcG$p$x{TzKP3=ND=0reo+;w zRBX2U*?Crdwk-IuwV7`{M=fQ#U}7?>Zw@YavYwaRqyb%5z}L`U8x3Qa=FPO4lh59d ze=l{lz=L;hQVKb>ds%LS*x>H!)TC90Q|A|VJ1GW;HRb&-Z49b;Wef9ti9H?a=)TxiNelaA%tNNj`(Ci6xEBE^a zg^$j#s>bA7H951HxkL1_2oR2Nl$7b`W{Rz!yw1(`+Wz~P%Wd@hyAE%ctI$u>e=*A` z>JJ7P^?V5*QGE(~uZw&MKhI7>U(w$Acj8`}lBHav(vM29qP40J>|b80ii%{_@#Wia zg`s?xGE&vx?Dq#!IIKGzjjlR>$2O7|G%A2;rC!sAy)%iMgbr3K+fb6#NwhjdacTax z;iOIBI+~8K%w}7#Y(EV@cm5cXe=G%?J&ALqq>U(EJ$N8LE&YC0LSEp|+Aq@x(WWYcOsM65PhsY#oPe)|`BfV&J>xqlmn|*g1@otGZhQ)+U-;I7f8eQ35yAJ;eT`f|xf_`r1#f8}me7pxXR=~Ir&PmiVwl#8bNsseYW>}Gygl3`(XuJeU_ zS6KXY;*y&M71gvh`xwhAAkI!%hK09rgkXX{gJgonOo$_b#*X`PUs!#XQ83eR_4S+% z4iQzR`B}WE&-zm;k%Tz>?FohGsqC%uaWD|m>9S%97(wWorb&CXe<7D{5oM*JztA4R z$}}qEcc$C(Mj72NbiS&)-1Tz2gAM$Ppnhv&)UA3}QP5kgL4~fv<^t@GX<0H%MkIR6Drnu;C&U z->EKr@+)THW|00nFJo1j9*07oX*uoprBIRtU5+ua}lhFDmi@ zI#3o{#|ygOIp}mADQZ}qQybq;3A}p-DsAx6M=26hf38}CdJ2>!z87!O{5i^r{F6d1 z)osp9)cu084TX3r$t1Vp|3DNYTUMnHPry9gXQ4nD=5phd?(IhZ7wklrio&Y*)YxOZ zgG1`DQi)~KU-^jm6^8nG%OAUUOx|F3xf+aCUz0PzfdtS7B~T-49WgOVMN58YkHn;`lNzURynw9h*^lVSny&==TBr zd?tWG(WBox;#)C7P%g;C&+me?vVjqIf5Xp3F_LhCXdbwp`NeHZJ&25gzPhi8l%R5g zBdP!sU(bI3>{If79i1Ms*}nSz%)>44tW}$a^!k_{@?ZI$fyiUQkdsk!sjU09dF2Wd zGKmv3>7}da3{Xc%@nvm}M|Nw+08>D$zhTk1yX$S8&sX}EVulLB1|68@VIpUIFqIM5 zcYjZFDsx>k2?s9Bn}KzB9SgT(cLzUyftSeEn_t*lB?*)pvb)+xfak>R3nR`f(8w@X zN8sF=3StQZBqyszyi}2Ynvtx}AilRs^r4oYe9`h^RQ($RSukxg#zC2cN7+|`hsB)> z)E!ZK_tla;Fi}y2LPmMxe%cVP8%lJfZ z%cYVHv6Y>me^-$a;*CG&R6Y3D9Al-K2;N3^lnk`4(l50GuLE_uA@HH&OO*?a_|EGMVK*q4|WGtOn;S0 z$Y7LXen78C`)1xTClhR?=*KwU_h?Zm4}0*2gN0;zoXBj@OSEFJv|0Ffv{z1$^Jxmo zxzAh$1|Qrvh;b7^iruKQ{5bWl&(>Y8%dh2p+g>WCSTB-2DBK$-w~@o|55dzEAf}Y4 z?yTZ}Nwa39N2fpcLcf{d6&$Tc1bI^-E7K0#rK9cxT8-6K!nsv2*M}6i;2J-$2V+o#hU0$UZ>RYc|t;37MKh+Frh$l=y zQ)9s()CkFnonO9@Xh@Zj@>=iTJC`#qGCBx?=INZb^O2ElP}~ysf+{pzo{x`!!=7ga z^ZjQPET6Rk2b02^A$GSgk$16Ci&@;;#7JNth9idnVx2Brz3m-Tg z_($EJHn)-`NupqXe!qe*p3IXjLGZ%Q?%uV?U?Tv606{Fo^5qHkg@4$0U}XOLxTziI zjf||Ur8BChBTFhW<6b)5{rFkTOx08e(~8ZuhHsBT?ycJ@hMTVYaJ$XrBei~eY~$fx zE=RlV=OJA@RIjfSSDOz%R6kR`u3yIDZP1Pv25IsOG^dT5TP`tp+d>;&6k zHGjQ`>@t|0@0rT`uzx!j@?+gN$gj&V%*9!hROQjfa^3kV1*v(qJ=+KS`}7oKPt9iW z<5ox=#?fbfJ*j-YO(*4YM!bzaqh6!;nVIL+bP&EB)}>=u{#f*T+L>PZYb+W# zmjOwaF-8kE4%*3h`3V*Od7OtB_uqn-bw&$gf5ab@PC6swgU&CL-~Z?@PxHxQHb2F8 z{_AVv1$COlXW3#CKi}!UN9zCe4^Q*+G_#{fPQ8?nI8Y;pKv1n%hUhcpSh#S)Boo;$M64m^5^d_|9Cu% zfBwhQ`LO!$zl;Z`!T%WScB{o`KqqDz7hJc~=|7I@ z^($(B7Q#&CJ<4PF8eP^E~Oc?P(v4gI)hTt&TFe zQTs7+nRT~y&t7}$YtY#)v&~WYw13;jUv1T>SI_B%6fbG*BB;ex0M?q?mo5%2Z)gd0B_mv55-Jswws>z0=F~EBzw$a$U{VSHoka z&}prgYi`=5@J0e;#jAH#?Ir(@5-W_ONKZmwNlgEL*Rq`{BE)Z_=G^ zw%cxHE8G6IIqc7DP3^Do-$u%vFQe2jZ|3Jx^RZ|(XN#>_f7EuF;~~yoN5y?q57P&8 z8HrN5GB_QY&C)WQ7O#)|d~i8022ziz_w40-`daorPL-F_wKZyr>t|>5f1dBTO11g& zUbWGCGo8}YwTY(g(wLf;V=ov~yKf&Kvt#klxXxzlRxh3rpM~{jcC9~6KWNPtaY^7T1NrGl?! zVfvM;2A_lTex7Pg{d!TWy%(B`^|IYrZ)fFZA@lzJJ_$nGU0!OV zQE|0fer$%}Z28_(#rr`V-&X6vWg1>8&GPH@)ZS(nh3vE^mb=0Jf3O#YR{9~+ZkkH# z^n9I9-`jfBzvVCY<0M;rb?HuY_`Ft|tIXGH`}k$&kNrpPxPSc|j-%ReG3}=H!R}u5 zTYh@Xo69N~sM<=jn)|OHYPN5?%i^UKRdTzfTE48Cqv}JSqG|Zq>3$8yV?As(l=;}- zY9*yI3zLnvz_OWte`JOq$NtMiZa(^<&bZK>-zuf<_h4n|=wdtIv8Yu4qmYB0F(AG5=;Szdhg4w-(hBF}1NGq2Oxc%6E` z58p4@F!kDc$t?7|9Z387{&3S$?)GtBwsW`7&-1Alc4o^-e`;LOxlC#>-Cb6xsCJ)> zzV4wpyk$3=+2wjG6?WM{lxa1~sp@TWTUJNI!MJSS2Ay)fTUxzO&d1i_kk5W)UUHd7 zb!6ME_m{#;rPUL)wJx4B^}%tR8O(JmKl)tPX6fCuZEAyUYT`cbU)ysrsPr0oa{a1& ze6CM*v5Caue`{hZmy-?BoqMx0$?hiam4o}p&4T&1lDW?6_4mvEuu8S-Wf$i5@h04O z-=!P#%3AiS_aJ9;uOH(~X`HQP-?Q)Q%Ds5bnM{9TyW*|#(VnidwUn&7d{%yzw%KF4 z@;+)@a{Z6##x8=@aa=XM-PLSQ+k0*kv{%#9;x?=mXhKnpNGas-(MS@F?F_&2ZA3f2}9w-l1GRUuxPdQ(^bZ+}6X#K0O@=ncga!9xSGp z{yD9-2PGyYImvC0{aRJ3S*3lc-nY_J-1HXSWWTY0tLpUa_BMQPw)8FS2Jh$lTA6#e zU6n?sf4UxqpXpXN-OJVGE-lvQ)hUWn#bt2TVYoEWhfC*MgHBBszUnu(I6WHK`D`}t zyKX(R_;}5fN3FN&=_U7C`8tcvzEtY0F3003y1i{G`S{!1u8Yw}-<^u7uT8UHYMZwg z8@;{l4~?K3Mwe6R^E}=bPm8OGX8Er;pKTqYfBE(j=<=v`>}2M-m*S>f?bQyQYQ~QC zi&^$#n;Vu|vyaC7mVd8imgn-<<6OQ!&YAo0TsW83)xz+Wb54C0I_1S|zdCgGEnORy za?AB;Q8k-!>Mkzb)!uA}(O8VqQ#Hv&YM)8F-IuKu7W0=)&{(fGUsjyvi;a5^uZz|D ze@K5Fy2VLxG9LC`3xj55UbDsb_D4Qlt~}D2+#y}=xOAbhNtahDU2aX&S&>dh_aMLA zmP+Q9s>*q}k;~oYg-n7@9TyOhm9?dTso4y>> zY5py{OQkK`^}KmM7nileZP;7Nlz1%D=SbeG@tF|sx3hD~ zEl(-?K2GT%b*}bH>5o<^nA&>!MRu0O$*elg+reTonB6)v)7iG=wis+nrZex%f2M~* zRu;>t_V)dK|6Ux8OsX+B*>v=k4pZxPE;o5ylym0TAM8rE=%dh;$tyXtaDD0w_)k+W7x%-QqpS$^BBx_&y?4dnc z?O*cEV454P#_LV?wm1Dpd%XMzf9BcwVW2kK{@3`>lON^o_;k&8hmZ5?Zo3}VDr!F3 zjaTFJU{D$qJNo|q5w!QRa&GSS`_k;Iyy{k)x1yQ%JD0`o?cMa2gVeY~e+-Wur=l<7pkXpF)TWZj7!_?w1 zKBv;n%lKde+1))<=JnKGf2nYJ?(G)o-B(cRbt?T+qjXQFJEK~$RA{`fXQRokn2Rp& z_eZhO6RG|5_0|n516`D}TRf7Ncxmsm%jW8%QSFslhkU+x>}8jkqZ8djx!VcedXrP- zHZSdqrERU%YTg&3cDyt@(XLnTXL@?}b?clC?cfnzhK*`F2&eC_e;>C|s(HVsW~Z;H zX!IUQA|OJymvky{`}NACpJ0>K7N&!Ct%8 z)HTcf!fm^_M_*s>@^$%AJcgf}kLtJ*ZK{nRy{Q!1!(t|%D~y)gQPJkx#pNTF+h*n; zFV}3goG)C@FSo58f7Vi|RIZ(!XEO5={ps;DyB%h4^V~I)xyAuuX1mTVdY`#o>b=}- zXFjr}pqVWfX1Q`X{{PBsbom(Ps^vyAa}TPyT&ik&COi5pr)OWiuj(c|Hu{h4(k_?x zb#ZcBMyawKNSWS_9$~Fk&&XVAI_sa_FT;uJ58o=4b4S!hfAdGhu3trcnil1ks9vl+ z&YiE+v~w_-*SBMF*uB}#zI%GO=G7c4Y1wKlX5){-rqanZuci0beD-#I>5T5_>bbtl z7H-#K>ppI#Qdt$=XQkeJd%QM_@yy)@qids`8r=q=%Tz1*{mN?dny>WYy<@FEJ|Cl3 zb$7?p_nAOS}5CvObs2vu3HXXn&>q^;~@P9CE>Je@c&!#Si0-v+h{U zk7>Kf58oQSbpC5oOy6&xk469Uky?$f_n>^YquTTmZAJUDK6!V|Mmb%WELGKe{s3AQyc5jw?kHx?@_z4wC8;N zefhX7#dJ35A2<0%?og>V)Z4KkKL?pOb~()F`R=Gtp1~G90hZ@@0ECN_#lnUxugGu3SIPt0?T z*Ni1LUFsba$&6h!URmklY@1KM9=%QaUarhE$D)Xw`S8}&gb-B^o`+2o9 ze<_*DKkB#MsrRTixAke%yR0r_eHop5Z6&n49UEWk%yf92R_uE|jtEth)~~xx_*vMm zO67j}yve?$?Cbh5E!_)htJW_{Oec?5-~x^-3u{cAxWm$^`dS z>i#lMx6Ajp%yJXPS@$#!@mw>GltywNAK`8HNR3{KD%fx9bJsWfoa#?ZZ=P#rfBU^s zpojW4e_dB9Z^Mt~`BB?0UpKwkXQekfv_AFn?Io8RcHPI}m=CY-FS|l%^qI43mu~6w zAwPW2ReP69^m?1s!+OdLH=FrwxH`$`%SF{fV}9sQceTU0-YION$9>RQM|sm5b&k{Mf78)!#AP0T#$jhR+#JgJx5nVw`3N_QuWGt*uHR=- z`m$&(&#m1|WkoMF&$qX^Xfat_iXW?aFj|aekH_Y1I{NtRtMO+gcWyM-%WP)do!;lQ zbF^y}i{m2!bGe@7#9dzXqSKqHe_Sz6Ct9uf zDIXNK$4U8`>Aah;wXDuNxqRz7)thv+vpMf7@)k$Uk2u8C;aB;sQJS7Q%}Q^!NSzy7 zb?dDUx$|LHs;92A^d%5!qt55k_Vabo{`kzFSFf|y`*iaa$HD!w_!6f=EmIvg!o@{2 z-zM*>Hx0|_MVKB&o$>W@f4Y8F`>Wj~UoJm-F95y*_`OPxpqsrlQ_f)z|rKWm+qrXPx`7s$1pH(KyI; z+KrE(If}kY)$5{h-(K#E(U*M;<>IUDT&tAIR2FAhoTf7K{odK;e|(qwl9g3EyByVX z6(Oe4c$s=}m*z1n1s(a?91KhO+eYeM?PYS&>R#GU_O?4M=!QD9-Z%Z(%RC$x>d}Xg z`%EeS6-e3r5W9BszHFwe&Dvu3dCvFRy%Hq9H&bQx+s&GC=SE82o6+l6e1tEC()K%3<>;f_a_?m~e?PRZ$I5A!|6De5YWb1P zrfN}c`}NxCj)L1&pWe0Fo!>vJx2$TK?#E_VYhEiQw>{O$h2_Vhs?VLya<4WoX8yj2 z)4N-9yjR6&){7JJ$F4peM5o5+y`yAL%-&sAe^#1@QEw%W=VpFVDyN#Q{48(Q&01KD#hqg~Q{k`2MOl+3ay}T$GyGX1!RL%VMV@x{a^l zAy|wv@9E(xpI7Zmt-Id8zOHY((V{rqf4#nZHEQMdDnCt~4#EBWnT=!XNqy34>@IKj zw^Hh;w#V1{Wi@NP?dNLPYn6tJPgS*p294zKN( zM{#f~?^Bt>@-h89&FAmiIB3W$a=Tr#Ezadhr#V_)&Ruzo&&1-}Bz&2x=IQk4%4J`_ zrQ;oHa9&qB*OhK&&u_=iiM?JfoBtn0=ds)<6h*-gVnGsVNzOU5BO`JK@%6@4vzQut zB*c67f1GYv;HM`lL}+p7Mn?OLCoZaaeqTdg)b*z97`cYt>biDpKZsP>ZXqV2>&b_& zX={|5H7-ibWi1jvUxy6dxs~w{DMnlhE8_Hh%^M6bvKe2@#t1~BAeks%l03lj=_j=L zhh*I+=*PA;8bqdcR)D`yJ{ai(?O|S+;V>rl3Dhn4tcFD1u5y=uEDbq-t;MYJ!Qv|z z7v>u&QXs^F60a`4XIG)H-kBKBm&ZDXke9+w3-c$sDDV2xq7oow=xCm0zt#^rccabS z&Qo7L%BRZGAoh>|j5JI&1In|hN<_o*aYG!qpiOiVWc51SJAh2`C&8_3bgn6D2Kt%Fvk0mO2Sv3ot@Y!yJCQBp(e|W5; zX83X0@+AVXhrZmH8zp+&b4q;>8g?Vw!q^Ijhqj7kXzHPF( z1*0y=Z_mJaRR9wi*u2@o3$3An8>xZFKAeFR*jAb;4dJi06;|dyhlG!I7175S)XRjF z-N7i|WAH1FdNaO_@TRB={-sl=8hRpS2EJZ|fSY`}&B#uC1t?@bhpL()c^)%X3gK0H zn@7oefYvrUzeYe477=cC*mP61C9Y|V03-Zeh@|_M{^|)YTJgIbwbfid=?jY7R!IVc z+qT-?v_;NpJ-ss9mpm0G(t{#lQAkkp6S-yUa`&K$nm^KI*4cJt9O)}3rM>B2b^H#= z3T;0dfZX%uDOzam#`ZRl=D{r;=O_4=rCbXp0Z*6sE)B(htu^YTf;MseQygD#c!&Ld z8+SPI!+^7Pe)25~Ktn_BYS|#@j23**zwDR$yqM-L#&r8TvseKP)_^9z_V$YXcdD`h z-kZ(pac`ahV@6Z;?MNbt3ss!s>GySl=<37v6LQ;4xZ~$5hY|}J{q+;QC|dDr{2WjF zYZhElkXLwrVVcoC+lDS5D(Q}QuB=|V>|shWr_A*RENesL62<jFT58C8lAHQcj^*2}WT zS=&qYUsj<3ju1umwF&}WJ~&rQuw+7x!#dJ$0v^VfaP0{gfBjV|c;$ZiN*h|}*%C|L zV1f_`*Wgj+ztcQ*b^7iD{J@MXz&QPR#gJb{DZ*e4mZv}^#v*%qwz8lR_9K|yYcZ@c zjf4w)0F^md7~i(t4_Oz%*G4V(OgJE*KdMP?XrP);aS~wJ(s1@lHTay)WPLM$YojXH z6}v!WKp%hHH&lXLX(ilbz&6WJ_q7=vkJynM#X*GYc} zg-2yXue_2d@o1D^mxwV9Bo5#2?UG5#Wb}~}Y`O1LmyTZxE`M*Z3h~EIRMmFJh-G1i zUOu;yUD9ch#_tDpT|kH|HJd@FVmf}Z*OEdH@$r_l=`YVUhC~fBUNRC~#T#oCvDZmO zXS*VL9{Vv4-EhQm!}LhHcYYe(~i*r~I8vk=Vs-orlx)5hexe^X{$IA#~Sh{uZA{)4$Ml zL9;;|g*EmD3^u19(>;!8uOWY7VE+u0>NNY@T58cWihmxNmImpwHb0PuteaaJR-Fn3BRsb^iqn` zFtGKlq;-MjQx`(6R)PF;weW|*%mFo_8WhkzpHRmEQ@alN((&K;?-}A{B35g?XF1tH zbXQA<`G4!HaGvp_wPDr zuT&n)qMaji{A6lo&;FLbP*{l>a6dz$-?4*tJsT})P693pjSMZ@!CMv039DausxhRhmgpQk^uF!>5SieS`q+x4bh&i5NU&#CCyc7X}0hf`wuf`8l{YXB6OoFMdKrlGB7L)Hy-9{|diX zzi}%Faw{3c zlF{y|X5#^g!ji6xQ_)Vt#9VM1y`j=z#2|Rz_(I$%! z!J(d3nIb^AaM(&q}n#5?0Z1=I`7JFSl=f_1Af7Gp!-2~1!lL&~YxCy#b&ZZ728 zoiG6W^hE4)qRZB=CZr!FNb1iqyG+8gk!^klk@sOPKl~-L!e}c%J%4EWL+T#}fa-as zJbw9_0b&SEAm=*_OBRjJl{kN~_5rxEPtwrf@PT=_YLpntZ=(v_#5yL-7KqqR3%)Zf zT|UbQj=b2rT=Pm#jgXm(vm%mahY_n6VYMok*;X_5+>X+5qH7&V6x>DYzkMP>gaK|c zJB{98Q0K#WxSmM<9_&56qIUxgvrVMxsL+bLHSA2+#e*E*FD-&AM^O#a8-6C2df|#O z>SPvQm&j!cP=B_)+aFbnY_@!Rmkz01C$Fuqy_TL$;=s779DBTs&2SYbT}H0hV<+v` z65k^OgFGp??%inH@7nS&v1Lt1HXBSb0E+nUw$%u}vMjIZxMPa%B`u97Y&>c%#4(c0 zOx`4(Z$e%V=Op$BXNsGz7#N>T-B9L(<2Ff(qzYPGXP3h`4M>0ZW@;TqJyqBmCu4>? zg_=lW_YpteG<&Dz>07>$`+P00)*dYpQDm!NtyZKVO0k{MsI@)d?`ILkkVO|1S-(Tw zRJ1VY!*O4%uopPrtQIkTDC^sez)KV)J{@U(((o{%a%qVbgVo%Ko}GEMY++oo(NCiD z`~OKmj10C!Pd}H6ISmbe+2X$&zkT*Y3uWN{l8fZ>c+)0VXdr{#s41*YTkeCzv}yY@A#nu7OBnAGUZ##%oh|sZNQpMs9cv?M&Jp!}j4P3VSm~=TP{aL3PV^~VFD%S}Ff(L)C|fnDd`gsV)E>*mOHkQ? zAo=J!Jf}32+Q8oEuu$}@1=sH(r38y3P)n$qm7$7=e3yJsNzrfID)h4>;&&m^lW2EK zIQiWDT7#n?=51`!VSuAff7uj!GyFcR|WK$lZyx3<0h-OYZz4#?aw>QX}Amkjv{7&Twj*4lIy6QcQ?)dEL%5@?(h?j{0c zqfmtT=Sy1az+8?BXQi^ZT~ka)%y~)h&ZpKDY<{(uS@{VfB(Wul-O`8_9SM;d+a{#B z{p0XMJ1)-jow%aoyw`ZMo6~UoY?tah4N*e4W%4^0Qho+@Eb(_f<0u1`U-rsPYWXzY zI!?_UC%FfoZ`Ep8eZMb!=XGKz>CzWAvvPSRXW%^+9yWv~Q)Asz`Imh?4KV`xmzRWV z3no`c`*KD=x20^_9sm})0cdK^{4m)oaD&6ep!@j}oR3rw&F~JgP;lnT;x|d;W6K0W zima+!z#qBG)4o4k{B(qTbWVy9cAAv+nUOWa*+uH8{(>RBd*GKXJ`E!QeU~L{3nzd1 zev*dp+su7VIL}-=u^ZFSa*hSd6I@;FE72D=TKx|Q`rY!X0x5k0Scb>IuD(+yJeyu1 z{ILx=MT4sDJk8e1-XF@0)0(#-#=8kq!Y=Ps3v{PytGeR_e^CZ0{*@pgFmHeY(wTha zn+N1L7z$qTWkf1ovlD&~T$2gW|< zX>AJ+f4*2iWp2D!%NF9*{F6-mG%i3VIiUCz%(-E#L z!5&U?ITX(zlr_}0CG###ULw9N&bridKV)EZm-lT889%=gllOeBPAemfqUsBw&Oc&7 z-Lov1!DsUhV8KrbhR7yJQuw~s>o%)|2^Px?m;oVufdEah;q8SmRXS;g)|XFi3mzZ& z4a;*M)qSaSGkC|ktlh@w%D`nEn)B~Y(UV@*8m*U%ZVNSkejjmP6uDbq!zZA$hZ=eT zjxX&6VD1QWuT=43cia5c3Ev97#ushFTa(ZSRG64bj;9)BMd**uD_Bx|#MIIAyEJ2$ zOWFNtB){(0_^9BoPvEw!aX9MmSvh?zk;i|_S2QjScZTcxlg?swdLR=_qtxiae_hk@ zUz3bx5Pye8Dp?!5BY(4z?3of*?knMhH<+63#ry}ICo7iK>kESRcbtgR$0;F1Z(EJ< z;ake?jC99klg*`?hch{O6~9>_JaaJyh4q((ZwoB}zn9-Z4IzKt)+R$_XY+Huf_c!I z=vERX6!5F^Zoyyj+f zKkxgC)fqVG_o*Laoo~1yJ;c0W2R;MQSVym}Ce#9O!tw&qhfg~PV}6&OLJd6uFPE@z z3l#&cNq?8fa0`q9?U#W=4IVt(56b_W3NU~A^$-FCcg-bF zP%bge3K6&hvyd$gL1F<125hxW)T|Ee`d4UiPUh=0?-p;gxv;!=U%G&6;vk741r2z>8yKk*gwP1rxq*Q*dyQWC2-!$u$0VV;VjsuD8+4Dz zQ%j7}0Lg89cp&?iP(}?Qmqm075ih?fC{@@63@6^-AVCyDjH>kT|7({k1PUR4sg2~%LiixBM@#h0 zp3pY)9Ys}>m84kT@jah~6A5@4aKW-F;>3i%_v>d*utrW7 zS?iQWvl&L4$^=zj-C{lvtCnR9ep~J&q zz76;^XTOOoZ=4VtO1^)PsnW9Rieo{X6c4A5pt@04mTWz)%;31+T+GLd@hkpbx;j>@yy1V3!1)m|bgU8(#t0RG zWfUjFE(f~g;#47u{HDZs@C(l>gC9*f#G04{;B8LPKO#Qn^2RbfykRXlrSrNK&; z9(&JI)#y66X6JwKV))c4KQc8y#RI-&*9jpwUzYEQ(slCQ&^mda#IcO|Xb^9H?vXYX z8Ta!&{8|>jT@$t>NXu!JI0F+ytxkykm<@s^Fr9_1xUGfrJ4p!fYKZX;n8z85gOzQ2!x@?{4FV3V*NtbQ z>+I4WUJu8bxU~t0Azfr~Qq~QS2xl$Wds(VIVy8&+{|7mU*m&|s|A{5EQLs;DUw{wk z2yvU|kZU#ntP@)h`h%hjp#o@xTH$y`$pQ0Rdu4<{+VZI>du#ae{s`>6h#Mv|Im=St zT^Ol*h^l`NSjf%#O_*`{`3XD=kJw2K{5y)IZ?pEzm)+O9$V~Z&xQmQm@3(qYfzhqj z;(rPuJzp{F4$7RzGNyO6Jr8J`1otLLp)1jQUQz4Wq>huNJ_@ z*!if~B@i{O;fNz`focbVjJFCjiR zq!u`QmxKrP$y%J<%Ar0+wQ+Ra%)JV%EvrgRnY#Ro7ZUjPU8{?nm>PI&uO_tnc7lbRk-NMIfjubXYj{J{FWtNsn#b{OLn5 zo{r{|s1a9x!F|%`!MA|@L(2LvHX&ZReO|8QClMum5(|||e;}BeW*-Hg?c1p?ex2!@ z$fr&FRKwbsj2S<>bHj0#Cur|e{Z_F=2#UQ!vsj+kPo)UYa2Cc%)$=f1J5Y!qU;OC* zcTmE`aJvn?%;=rCeVv=>_$I#-73jmhUyg6$OV~_Vjfoma3i`ySwP*uN~!MJX1SJL7@D{;YJX) zcK`4hv+Qy;qxHbl`*odXDxJvkaP9q;2P%6>$ob5y9vwSXWZOIJFQt#)SGfW0w_(6} z7YoEkrpt#_E{Kz}t5SYh`A=Uk&Q&g1wvv~AUlX&9Jb|JKuO=O1hVSF;<|wocF#9eX zQ#I0;Zwd-cf3(Fd_}1>P_RBugMlA^hS8l-0t+#$t-)`Z&QAnU39{u)6F6~O(g%0s_Z~cqNbVZVl3~6BxyyWsgP#juqQ+HDT)!-3CgwBIV*fvT-s3Xze_T`X;v2CW!hb z4T-x^$`hGLzTT}DB2d!@0i)Qjt|p*K?u47ysN|orJgRi3zJUaM$Od^qr;A!j#pnqP zi4kbW=%Fft9d7P>@=VDa`tS?=F4CFPFcn$bJ-0Dh_2>1QN;}_vCKE!qYK6JVE#Y}n zk3-yZ0a};43kn;5-1n8x#8qWAo%C1z)d|n;mOdsKCGtpCn_+)F*QORd)bQ`moapo# zZ{EPi0KzMa9Bj2Z*vpJnk#(mRg{AXUaz=48z`PwA{UAgF0@^bpU1S)JN$kz0))4^_ zGBef4OL!)(gQQhyby=X$z`ct#W8e6q;ZpL-cJ@knP30heA_=A9Ll@;@wRQ(gMGM57 zhDPM{TB8PWx6|i-b((}B`cuN?@+=gvlpiyCNV`0vpmVJupCTSd{5zr`QD}vwT5G8P zQfG-6Q-VZ{Jz}Isw=lra&QWPUe__>{XJkeby!M6(cK}j=wa6=H;bD|joBosZ7vlU-M@IW?Q3~u(eLaR8cSJur7TCKEeomOsObcs_veLRCA~5n!-|b?-|ROp>AjfC$U%bHPaMf`S=6>dqY%Al)Vo*5@o)MaOUh^9 zZ|7$dZ~b31jPtZlcb z0s*m?@qP<51l4yOTbC(+3oH`9^a^e)4-#5zXTOhWN)ki|RhMUf3qH3YPF{)uP~58? z%G%^;^j#Q7dYAA$X3;JhR~0BrG=Y5U_~+hA#%U2kc3`#h$)Zc`hj8H==Ig2EFDo!5 z?Fr#7e~znyY94`8%rH>$=*7oa)38haKezi&UMK|tQ@12lUKj!a+_ybfUiJf*w~Px9 zE52IQ^ibMV`16}D`R+{_E84?7^jXY;Z>EVVX{B4P-+m#a9}8Li@}(!Fm+_1X6n{c1 zTz5GS-TC`Tcn}IX*=-2KTFF`e2$Og|>aw&3z6nA41j~uR-puO`Xu`1A?sU~}(`J(7 zdHkXv4%QFT5@GrIfxm#zTeT@(qaJ?2^|McAn|os4Jk62Y4UR@;r1uq-u6pnywsqmf z5m64eJ09L~8;DS>OtcP6l=x$&zJCBOHgIW9h+E-eXPSPtr%ubX70pZc?WWx|E0G?` zVrRY(nWJ0>eEk=c@&#>Y{*_`&_{sj>Fxbs4FC!q2c1I2J8&{(teuXBUuY+e$aKl+J zwBOI`2EPHM63YO2(j2kpnBof4b_4jo*(qyQj=J!w*x7dJrd4Zw4Yj?uk|u z$d=IfV+C?4w!UUPRy`N?KDYZ-OBK%~$@!2mMhIW^P>!O&OE&QcJ_EmubrZ(6PMuv6 z*iHpk?g}I!?I)pp<4zR=x__{zK^4U=?izMrF)f~!X#*?DE?PA{mhWi((8h8G7R_bg z=|?T{lJ-37Bk%{BGO2z|cwyi)9Bd|c|?Rd7F%DHDe z5gQL==Dwnt5Z^g>OMf)lLWouSmkl=js-!+47qo3UtM7^&D!Qj z9eyu1165=i1YHOA`ia+g(@z>*L_znFkW2k}kWAGEg!DF=MTYtb0!_U59to?JhL^Ie zqD|XRWMsQ285~EMGj#3+r{acaOXS@gU=V#KrZ(+aDXGzqm4DA~q{J`bZd<=19i!qF z6?HXj@JKN2%d=MBgrSqp%d<=Sv9mC=`tQWdPMwV((u=B_E^{+vH`aT)5OKF89OzR> zbvXF|gLGLRMMr-O#4z8I{PxixyRIXh7EJ7zmJtUj-vxR<5dz9eXE7{G+)Z~Oh_{y9 z7(dnLp)(-*{(tr0er+OK>J2l&D!=$| z31K-XOc?Z+Cm{+)f9I=zpBVa1PUl3C8o>AkW1ahdL2kw(pEpLK)c7Fhu*R)kgx1#E zzjL^6S@8V6$)T8DH85!amAFUECo(Q$F&vcoVz#`Ju>E%}V;D_H8#NUS+eDcNy!qsc zp|Wx4htRNpvr33&_%AA+#%{9;ecN9aF(OGs7Qpu+fBKacFlu=6I&hkA%5a6bxPUp^ zp#>+Z;n)0zunEXe0J0G2UyVRMvMtI!o5}gQm|TO0Etef43MYSkztSh@BE9sIt8rP& z43FPr4KI@9(0k^Gl1KI!ZXB*VsX83Qsic**EGX30Ospq~LFV_o3nqkq)4iT|D$Yuo zdyWdNl#xstQSFK*^u93}*g1!tXu?uLI}K(BOEGDv|K{&2@-}vefEYh0S_2A`CF(s4 zz6RSOxq@bQ>fV0>NAj^WZ1{$ll})lmXGKmmI>^!~T+>btMBo>dfK?DFWfGl3#xHPy z>dSAg=aWWo__KT$1okQgL_zFbxoMW=PS{NIjxWX2^t2>XqMmw;1>Qz4tZ;&H*vNNDs~8YW+zNH;R= zH1V1>;1!n(XAKH}x8+h&FW<9v@-%PCDegMqZLeW>D`BO>`4T*5I|zD}K9o9#dR3t7 z{WbItBpp0q{;qh>MB{szIWXC9VD6hCBn0~6w-xp@kkKaQw5Y`uFM!L$7*`}SSOu_0 zFdC;@9S=`9M_zs!eqFoh7W(!0ec3y4A{B{8bsF_Crf4$hqp)N{jBt?W_2MrVre$%re(XO>?F1S`p> zW$L=gW=ANiB+l{e6bH*zQq;4&rub+Ej|p5* zX;(n5rvcWN4kijTfA>?GJ{7wUt2hLjyxY0*<9~wZ_{Aa9T3QT!wLPQjy+N}K;4@u;^7i2GC3 zC-a+cISD!F#!vbG#gn@3daXcRiuS!ak_PG~a{2zQO`-!qm%%0q77qPdG}C0t^Dfj_ z{dQ$;m*pl3LVtYe-bkviqq;-0)EC{t5Ui(ryrtBb302?2%BGZEWA&0K*Zbu;sFVzH zy7W3WGNcyji#I#~<|RIedk)R<^G{}cgq_VYA|2p+Y8JdfUPf|9ta+<^ca3u)O=bmF z@o*xgGBGRK%Ee!0+(xK*Tt7AUW6IS+Mg^y^WdT}zmtJcPA3S#3mbUg%tc@oPrZ&zifju~o zw5+NxpT595)SJ*jX$bDx7RmAvJ>sZP{rph@GIU_tgh)t$P%a`US!tJVC<-cnYvZ4< zgqqem=J!2?>;O~cPcPztb2ZZhLp%fldpsSZ4@cS1Q1+gCgpK(sX*kk&LbRUMR3w7$^ zU*k?M+MC(3(67|J#g01!{tRWmY3zqo-q9|Pr{XPQM&X?lyR-glS z2`-&g%vI8#TI_05PQ1aU&Yj9MDWvQOgj|8`74fXeq{LG?A8g~5@mW8zbAOgJt&Uco z4@_@~NdLGr07XE$zrESesn4((O{`3uwUgi~=oLqp&a{n^>=`AIV--kx0!M%PIzg$y z%bN#nj=JT9qA+6ejxT`FNPi#OJT%N|xv62WuJlPn^PjjYUTAR07Cl@VgMF#`#7IWT z`(=EW(J2Za7z zB0^mJ`~>=L%bY?l<9_)aYh2E5<|*6mcLg}DlFj!7IRRwMJbv4~^sPCd{Z+)$iv!u0 zzHJR3f47(F0mAChhRr-DuR3g|yv_w(fX}tl6!CSz-REN~<%Ha96<=|XHgf3h%qwF; zz7aT!$Hx!dx54xjJ01si#FkrNY75#3Er*sJwr>3C~VzUiWqd zxr~GZLM5Teop92W6lRz*xp|Wp=DRM6n%2wEejMkDrarqvbSljWh9F*a()LJ^g4Pkiq;j+_;0w8rl zxxH*BdBd^TR=QEEs=Y9A=1gKa!ObFemnshN7fK+H_tzJ!`i?Pk0;c2jOR#o4Ir3q{ zG@>gPY7H62SJ^+FP4mY9%AG{d+gr3PJMkL7fS_E`-a*)d9&D8A!oRwD1~y;}Cq$&m z{FmdL3rzuQmtAiSDFOeNTb&CU0T!2{Zw)bjN1JekWizp97pPs%^_rjeLn~={b&m=h zlxwt&rZdULEUUu)#(7?7IvjPb`XJuJmZF|KP$GSJ0!82iPS80H81iGhnEFoGvp->1 z%V77kqvfrK`}?BGY-uqW72YN_l$@V70EVl}2u87Gk6w|l2=2^)OvM)zs<*WWe{W9^ zc;QjodtFX#iM_Q5n*7GCml!PyH-GAjroZvxKb{rstatkoIsOjh+oEgonjH&)u084L zkCf+e)8_5A;N^8vFHgLVCo+if$Pm7WE*|Sxd5S3TwW)6uE6aZJG?{x;H9F>$C!grt z#slerRRx{H70`N%?r>Mar63ixiL;e-;+Aob9Uj8_!>^T5x=Cgr4vDovu^ku?WsG!i z6>e6m#GqGs?+fAVX|(Rcn@l<#2ft{S3ZDxifA%+vbJ@n)S!#+Po6a`)P& zAi9X1x3YfxMc(FxH_kHuy?zXB1ViI1d`n73kQ?FCt(UAW3Nt^gSsUiY*NffBwKl=C z+%=vO5iQY(Nd{Wp4t#5K9X=}{Ak7RIBE$mW!%+oB${f|c9-7b|=B0aE9WPYXme!YP zat$Yc*$N=mi7c%S^Z<6HWM*M}y68`PK;OsdR@N_^ig@+IGLeb9x7Iw;2Sm=V!j?Z4 z#ExPX7io5%(q*`34-!alCd_0ro#0Tr-XrV5&53Z&WfYCVT11~h8qq>bQI?A~62*!rZ%eBd89)5K-zn z(~j-jh*vf>A8OZYZbzQ_tE%j9dv5_=3-keff@s6KOPb(*mrHaFQGc$bdntS7xbFbiZ7F+(d8YZ9@9QWWI{oR;ExypJ zXklLQj@z22g0xwnZnH+z_wr#oc(plau87@gsP)R_&nx;IwXJZVO%ap>c^KcuNXn#` zkt$yq{Y)&;jrc6Z*6!}o^@LqHg9U-)AoB0tukdO8LWeCyzik&+_Za+JA>?D@L>V`?uZ8ZwaXp=PGT`;_TQ6a8|%On z+81NAR~3c@aZMbDRwcEiiu>v$1NFslQeGYM_kQQ^6Z0lD&)2(pJBLDV0g5c7J~#2H z5MKRlB!E2gGk9hrEQ6*GK7S6uCJwWD?Y}b%y%x}E2!+8-VFr%)%o$lvpOZ~*RYWyg z(L}byCVSiJS}i{P3fBoRB}9ugC2(5VVN$7=yNMc*vv7}#azKn6>py^|t~@fHLV5UA zW-=s_j%`~pziMV2?)dvX>u?AfyRLiYeWVkSQQ-IS3Bg%F)1%nR27f(VCnP4g%kU%y zqSn`1jlmEhf3Fz;+{YUDpN7Rzy^oy)EuX+mUn`biDX(2k>3#!BQWRUF7{;AK>Vy8M zTH>5FTM$e8ht2otJ3}WUWAOtBw{#J6;I@z6z6BJr8=p84H^rgRi}gbwu__zDiL`fJ=BWSHE

9IiYZeBpGn=s(95tH+2Q{`(Wz~h>P%5>I!XSB}prj|9 z9@Nc$mvRkKZ=M(23ALj4q}uWnrzX6JE7OMb#h@?)X0SJ?8ud1S(oZR5P)a>xO`|+i z74cZ6Av2u_EQqeMjlxFK?Rtv?aZkN}qt#Ir!d$ua>IkcHFTmW{(*fg30C2e1%NA5= z@@h_{#B^HK0zeQrt4W^)r3poK2AAnkTi!ZFz9+oKr;g$?gSUR*g-KN!Sf&76?O=YpR*67>+P~fi zUg~^$Lf&Tv9N?X~K#fzTrqkF%=>40b^cpwbY~7=xu*TGToY`4=xv?0K>RA0qQ}6;Vheo3*pSNsn_HJjm~ISTnk-J7 zf!$7!z`q}9((7LF9iE&~? ze1Upq@*i{8Z{wvy!X4n-BL(XM9AJ%PxS8qi5&v$v?G2EqKn^$7?cTAYYv=Cm+qdo5 z)g>gFuFV^^8Z80cR^Qu&*WV?tk(|cbQ?B~Q#%kklutb6w3#oy>g!xM|J;90_wyHV} z#@5}NHyfY7sfdr+Oe3;MbobbQoas%*NzyKk4g)RC{W4)c1zep#dF$9yW`-o$PtQI5 zQUuO8b=p2Q#xfZfP}j=wn$5`3`HN@xRyxo#Jl~v57Y@u!PSrHk&@HHY_Q;LmxjS5S z{>rz-`*?&i_w*^6sg7TpAG}I9M)MV*e$o2hBK3dvddMu!0ek`dzpWX6-g(b|!=cyl zUsmFyo&V1N^o>1sviR_lI&<|onL$qogXMKa(h=Ff0eC zt$4#LZ(71FuN&Q2`89=@*q=<`l`VLbLm#dfaN<}uR7Fj-Czk}-E_G1(>S(^!YO^Kj zxz|i9uP&^avAioHo5c&PL8$*;0L;G?R&u}R=Vf&Vw+#Em?U(Us%S5_ACSK3A4F za~~`#Ot>G5ANsL#_1@iU_zfq5E~-(*Qt z=S+cQMkz|^}R=|_t6hes|f0XY(=1AXbb;;WebrnsFzwVr=|QHPQG zDh{Fx1u2}&T4CrB3a!%L#KBm7Jt0m_UcEq5168287r4l4NGanS3+xN{seY{#)%)(4 z<9!NMl8H{OK$0APW=U?=AIlX^p2~QObQxSv=@_L;LgXU-WWr6{1dsn96QHTdiwUpd zF!`A1xrga9mlhCt%EvKXuod<~#!EM_vK((`1LK(hTT9R;R66uHb|l=H$sXaqC+XhK zz$1ZsKsiK4EO*e)dwJRDMXnhduE3_Yq{QHjdhta$-&9z&xa z53bHV_}iM(lfsWfUyc z&Ly{hO-2-d{Iz}Oo62taZad5ia^XiTETa$qOSiQ+4%gQn!8~w)rMX)$V;2x?A{;L^ zNA6j24J7r1nyw&mM*b1PPx#1uAz{;sWFnBDz>z7aL(_=Ca-;#Z$mu&vfhC%_k zUiwg$ZsPEr6?^P#sk^*V#$4cYc(G%HDpDc46zSJxSbo%(@rSN| zp(Q?w>_eaOim}3NHSI11$uCdauW+MA2mvLs?hDoMnWc+GA+E2yNbO$FvH1M` z{Vp{7>OPCm|I;x%wpY|$eJH@n`hPUq++5=S(H3rb?fIbx=h2!2{=ifeaodju9xxuPhe4aQ#!X6_&#m&=nTX+HM?te!T`` zKx+><7;=iAdShKG2F!mhdC?j*`in?2`XkCG5lmu>&!o?-YW8iX*)}Z8 ztw!`#o#&!acn}R&XmhR8W++I1|7&X38cxS zl^rA7sI(EnYh165YoPI5ts4_{R0wk`ft-ha3tjn))&qgg788XBbz#VV9lyf$(6Mc~ zE*-h-TMqUTfU6Al0C=MeCm4Pck1yqr(BQ_dV*DFcB)U~qi7-M4^d^&Z(IFdX3v$J3 z_62_Trn*a@?u^tMwe^{7o##e6A1KKjJu2Bt9W8a)AGVQzCCVlx*{S#X4E2D&s_z5a zLGd5zp_a9jiXcqEwo~VSvboeFY&cV7&%|=#hcHSywR2{FX1@uwO9vxV1Yb1x;GJK* zsXg~c9?XG7t@24@qYw8Jhpm_qsgHx0Cy@G@D$GJA3BYcK}-lJP!0>@M&m z*g*J@m>4fU6i12L_6ERs7N8D@NRWon_G9}^-&nlRfJ2(Hu5dYjtmVrpO?X@ki?yjI znKK7qcdKLfP}sIi z>!{-p+JNq{;+9V)&WQ*RafuR+>=*mjIhpsm5+c+_Z3TNK;~kt*TM21=X*R((B0*ta(wt>xXGb;WYMAmEB$4wcBi zbRoT7;m>gzsMm*6(apGoa5VShGJFG%$+@iJ87PN;QN2V7$t@?Mc)uu5M-sBiq4J%* z!n-*;vF}}Ykyu}dp<+8-cuJ1XL2~eO6L7%h| zrCngA5wkazY7h;T+5^hM z#n2$er&Lgug5cDMi`Bvxi-?;+}4$7Z%MSY$9lSd zT3SOL9W4>}5vUu{NJN%9!@;j&B@1n#@PDP`fh) zE80w=ozoXP3xkbqP%x5YUfKFsvT@EI{fDMRwo1ceqIU5-tO69TmSWEAEu><|K(lB; zMw%r z4!nxRn;W$`fH`oxO+E^US>^Nr=IMGxGi?C~;&QmY?@8z#;K^j72XElf>#gZQ62#WR zP^8tyK>WTOKFbq{m|@Q$h}cIFkW*{kd({|Z^D137SRgJ|H$R1z|VteSJy&h^N)0GexvpjvGoLH&|;3Yt3 zuP^jALaS_m)8{l04h4;O1Y!E$nG1wr6Z?RUOm+ETdG6Km1`PkATUw;8y*-*J5jo#* zPJf&bCLD(sx7tj9KT^hK5DQrQwE6=7`u4K%{}}E}*}}%x*w|-(rm}&+ZVSNZ^e?k# z+xA_Xwr$<{v9U+6^^c(=kBtzImK$OE8XE=YScia0MwO#Ypd$2JfU2##CKFSUdR-(8an< z>vzcLs;s~F=CW~r2iwXe1vX;j3|qOuo#H2-wPFp%QLT8-zjlZ-VP*F9zE<|g&jW#e zyk6X^dT_M>{RlS$;!LZJ@SF01n1R(sL_L!DTWv(&WIM7#*=nO%6%)8vZM0PCUsz9l z04PAK(TEX`yE+FYy5H*MzCRZzMRlPRr7{kf8>NEQYMR`CkDK^;jWn{r(r`AFN(Khe7{}QY#7Da>mt$6Cwwknde-r<>sQh3(jeVyGBv;OM;t}m9%fiALz(2{|W{uT}*xc0}2gODoPtQI;S$-HDOlvR>{ovbmSI+-$Kx;{zLX_~Yo)<(tQ zhoj2~C1N4v#VJO%%PJJdpj&g)hNM(ST^=TlgU^Ln4%IzU9D9a1$9|GH zI46k*JpGq@k$_M4FTAyDS9e!y0zBp1b?R*l$p$l2>5w`~AM*cgZra{;PQg_TnHdqVdsZ}fE`kbQ>QCoEF*8W^#?&i$=<^Ex|<$fHrVm3(W-sU zJyas<&`nDr5Yi}EWd)SDKWqzEcEJIENO~je#$U1CVOIZRMN40g!tjG2EvVfqLr_hf zc1dOSPGbOqY61gKb=1XC6%gzlaVeC(1b06DYiddr!7yVdsIo=XHq|)$DSuF{%?hT9 zylK87%u&U5Ud_1iuwH-?Ou^wFQcWGGGG+{wM_EnS$E0zUg1D|~?PT@MkJq1n)Z$Sz zcIFMJQoG$cYcoef9X5;O?Q_^DSo@xt`<|Kmo|*fenfsoZf1YQ5W^KnzjDbTA zq|(aIkTaK@L-&rCue0RQfr_)~GEtlOC4LJ6<# zTrQn@QU1DiSVumHrfD_}Dw-=p`7V#+R2PaagRdffn0-`v{KwNXQ{hbK3lEEC?Xyn4BRbmuDh!h&Ocehac~ zu0BMbPD2-{L$h+Ldkt7SWD#rSmWMc46gW~Ijm$A?>KmiLyYXJ!abh-}oyXC_icpUB z?aU3D1iz)Zc{lEfmD_{z{H!v+S6Jvs!o6srX~{j{BH0Yzyv=>1z`cY2VMV}5TvY^1 zSqyp-t0h#Bx7Hqimw)|KT`?*Rswjm;pezOTO@q3;h;cFF}`6X0( z1Es23lF$paFur&@6Y+Zfg%zVLpI!#WLxGQvaSH)%Hy>QvUOrvEaa#>lt8AZ|!{b+4 zDahgwR~Lq;jHfQVt=V{A-h>r#Kx^O!|Ds}xE1r5PjbmkhYvIzHPsyJB26;Nq;zBAX z9?~^+Po4-BVe0CFmf_RChpClw7Lr25-SHIo7_IvsK-R1W)@bG8 zDrUPxcrp1UsgE_wpWofS^ew2Y7z0ohDj9TD_>OTw3V#5Xkjbpn$)j!4%+A-$%ZIjdW1X_ zjQ$!(G8`%92NEIl|&VjQ}w^z=UAAApc?Dl=gef<1? zLIWqUf3E-(Wm)7>$&7B*Da9pc)a2O;TaERTtlZY}+4A)t`8L#=__K83b5<1g?XBl3 zX(F(0-u?x~ec|)k75I_SJxr+!1BmvBk}aHIY(uf|SIHme;#FN=TOJL6l$z)9L`Lxw zh&L#kqcT)bv~=>Hn?FJp;b4B)T`8wG>pRm6Zh)nG!_o|R9(q!jL-ytoy5qjSRdPl;p|%o=Lq1Z(avWYjc&4~|xr z0#$Ei^h13B;QahEQW)=ux*9 zb^?&^;0mSK_@NjV)t03TSIC(~$odyAHlE!fM2E82%+X_)4p48?0}4NH><2|ZujLE{ zpVxPY!cSedC}v}XQ?ICk|7?$cr~_5TLdp}~CrWvybBa1p!z)TDxJS3B8c)+#0tHRFO#9^fXpzD)1nnBSEnlj_IBu3Rs^DXo6<7D>P^Hy_!jXeps~Kx&q6+*P%C z%rc}+k@TXnM7_(X9x=Lq-47d;reUnO`BeHIp$@5ZYMs>EUjCHRHJxQ!_Sv^8VDG@~ z==HZD?`dR!-Nrc^9oVb4(Sg0W8@<-n{BP`ObfA{2(H?z`4(#A;v>P(8CnB(er;+Mt zq{{*LPPRYULyfjSZfj0phg%pnJUsy`j#w)1qSAdPExUf2*>}8uctyb3TDx0u6ssre z#*=efpS{45^2MkGj6T&wMv81oQ`+!K72SPE6I&}xL8VpO+jk6lgY$bwZy>{KZ}E5S z3ACG&x5^dhyu{`a;v^S=Mjd-yQ_ zpVxN(d0p?H*L41Wd26}fyeWf}iJ*j5Oag1f;*YV^DiC=N_r_r*x|#q2)F4F0kPLDz zO#^vCm0?}@yH>-5oP#VYhsj+C!wO(RwY-p!(lmIP92Qc+j3~*#rin^Q7KozCIZ2tC8zR)b$UOoM5ntFaCym|v(6 zF$5Db4T_?I0$~Ic{*?m7$z7lxY5IQ~!a^oXGuizcnHDk^I7S0uaDy~VbP{}$gOPlY z42T@conR|}-zSm@#ZlmhU?4JC05-xSq|BI*pg|uo_g%^$OSw##j~Gj%$jOHdF_5^D z(PxB6F070i$^b6_Ee(k&!Vn~2T){An=*p54v2`NL7mkbIeUJm^j23eB1@9OE!vLyf zQxQU_w+?yFfH@jqo_ef;f`Vh#B5dJ4p_B8aYO-TZMF@AXi8C zH8j&m6>JUF%oVkQRUgLa>bmMI9I~#IkPWvUQnD&4-tGLIOrX?87HF(wwFMGd2p zA(1Bgfpt?Sg$6It#}VKogX-QKfm@DlES&~7PrTHyqhVG`7821Gb{x?BXwn=F4U4Bt zE=`WA2!NDgU_2G7MVAqq(5 z&lVFjN=%~jFJVi^VMrY{FLeIJ(e7a1TNcGgHr{DX7Y+l-%5?rE8jT*|S|OwbTT$v- zEj8-02a%vm;K&4vod!E7>kg0$K`umpCNizY<0llU>A(SZvp!1yA@a=A%nYlzXI;&> z$c(bUqi*F9bNM2VdXz^A8GiOEKbd?Lp7k|@+YI?eu(#=e21{pWr!qngR`)=V&Yae8PI-)q8mQfAz;l#;jhl=} zrhP-#O==JLwgukO3a&2KQJmLL*l+hyoK)qv=V(G!zIPpE(}~S;jq!7+^@b`!ri`a; zxJiF3j0oSYn{>+_^S!%C@9ePxgqr}t9_e6F`=qI{SeH0PAL&!2woD6+l>#2ZFn_F@ z6z)5HryoM)TYYEx<B8lT4%JpV4OHNMRG_m(>~vfW|rYi6zjk0HI>W(!&F1vnC`xcVQLJ~cF`!@tz(39aD<@8ay;CH9VC{~mf0Q+aacvWGj? z;tOD3vqC15l2jn;7Kk?}P!Pfm8-Vu>>NAhKGz8kxwR5RKxp-55&9(qjDkq$KRi_qZ zx+3)|vbXi>l8sllCcLXtkBtWI4{G(=1ExjdJXU5ZQG{*jS@Na|7XDo&zSTv1yu{RL z318Ojh`ru@Urba3?OoD8o6Sm6LMBbAq1?c2eD?|K72z@%HG6!+J>K5g9`9f``93i` zZm^iGZB0!Okb=p7kN8WSCYT0E{=nEQA&j%*fsyXnVb{2KvKtJmV4Mf*7lZ@sAOY#1 z8goE%*+u_TK12&wFWawEIa`8?HGCPF$_#&D$O`RF|@I#@HCAS=S!eFF-rO_>qdxsG^;N9OfC^UP@ zOpMhAJCIq3AA(8<_Q&ucmf$O<=v|T>oSlXmI!Qhj2@Q=GWSJNLUN!%^xDpl4#JgQ) zK3<8K)<-HKzqJ{_GRa_gN7UfFnNQ?fhv{)T3&D76+n+zTNy%jVPd{VB8`y&-b2P4JWS}< z^<&OqCc?(U#X@!au<&C61OZ1;sssxsgkXw)9IuOUAyqjlN-d7C5IFk&;8nBII*nM2 z+81VKO*0|NLKdXtRJovId}_c?c7u>1*D|fTZY+67>ROxNC_vaWAVTECr2=IIggro@ z*4=CWZCd|gn%d*PM(?cVUi-G!j03G-Oy#GND=P!h>1x7K9SElO#yO<$X$_Mi>l7(} zO-&=bPLWgUXo=FO0=<@kn5Ej2Kn4pcr)mvIC?_T&l=sE}-SACK&&O%8HEm~Q7<@G; z2w$r15zmfSrqj+>8X|Yu& z*+gmbcvq9E?8&8i2-hjcYp9HBs(mz-Q9TWiuNf!!5EaQzSNslWLT%8fHBBD{iP0xb z)AX&YSufl^#GbpGE5+N&8&9)dz^y#*X`Y1KnuOTuUg~rQbcUM(N9o^BngX+CyJi^=ML+DrMa%Wl!R4}2=94CO)e}$Elb)(4z4S>R1UY0@w}+a# z=(7<78}$93G<8=$8ljKIjs_zU4~`F?_>bbb%pSTsJ3AE|XzJmA(6;yoOi+yRBZ4}0 zJ6L!Gq#R|#WdWkZFRJ=&7OYx-F=H@b24bK+7*rob{}mCfKWVOh)|!kQYOU8#g@MbC zT{euT{Yi6ceeCy*C+i#QC(GA2Fcwsb(nhG!vA%+rvqwa>}=t7(KjVBLSw`)%!xC0sS!{b}uuK?gm;Cen-4>)ao z_M-IpHRylk(e_VQO6xy>H^lKj%D+D=FW)PDdA4+6t$gOI(ytKb1)#gKR{rjIY2|Tg z`R4ZN-^(X1Y&<=UBiR1*`;Dg%a;d!f#m2LrF_dlv)GQ{+)0?D!SqQyxldR8q1Qj7c zI7?sr__DN?xv(?tsJC#`7zs&tFkj zl@`M;#&eAngYaIbuaI>tuWK&!7!m^pLq>b&9!%w_3#Er&lpf#RcyXNt8*HHt9W*|& zx<=*i9+kg4QF`%zYw4?V+uxqscyXS((=C@CvMLyvibYj^a&`0TvjkO3r%uuUGB8dR zT@g;TWpMIehL|L^BKxyB|NQgv*T0u9J=H34$WmJUvb1^2Yp{d9{#^^%_v{1)IwnjXq8*K?#o|_}RanP=bW#87`D(p%1r#;4D0t*K zA0ce>!D;fJ(g^qkA%3GhCb}<`PW}eYf>{37XQl7Xz!X_q6^5~LG*8ZzE}m6q25TVJ z0W5S`aQ9QAOM)?qu3+QI9fEoKj?R(^Ev^29K2PdC)S|*6HWRGl=>TpFZhk5aDOHeh z`{Hdzc?ffVz47Gp(yyQ5fB;>{++AFS>=PHxAnGtEsWFGTNL#<(-1_}{^Z`T54FVZ& z$N?3foj~78@&x8lHF(ruqI*`2>ccD@w@&@IdF#^l?WctF!nB+_wYh!|n<2`u&X;018a(ZjBK6L{NOE+7i8Ot3yL$yFUJPwdG;Gw{i7t4eLYv z?9i)!z6fWDsJz+*44kaXXrQW1|uc+o-m6R0{6V;*oE=+UBv|+iFbTjoo9d)^wJS4GQd~$K6>!s>Y96 zBDgQl)<^`mZ}GTq@wjjC_`WS3!Qhd_kfxG<3D{>FPk!_ad-=#Fa6=~LXo*^~imQqs z17sRt^2jP+G?Eqa@26bRN=rv9%$O6JV-f@0*8prllfSOQn>kVuO0|(A3bN455n<3# z8Z>UyXT@aMx)g!NwLjgYQ4!;Q2OzCJiuViwFr7tl(mybdhkn8|&whC9a72 z&hyN5f1rNX7Ktn_(6jUWJhJ=`jb`%=jSqDaFbpT(sJDMLV?$ktqnmd(uble#URyfJ?wOv^Xe`01ujx8Xxi8K4d*L5I$D^`NF08p*| zcGLZvm(zseXWwI7TvUY+?m)4`15M2GS>+cCo{JhMw8o?S8MVbj9SDZT z+jw%ObnWHl`aiZ#{}VHmmv5cgT02R4R}+@+o8Il4-n~21J7s5DXjo;!Xy~l%7zH7F z0d@12PnB;Il5w@Rxm~NN`YDzl`B;hNZZae~M*; zlKyI>TKd&B_2aDi(5%naVlh{k^=TG-Tt^n(To0}F^tO5!AQ1Vd?PpgonSBP)k??|v zaK>OXBnn|*vQ{3Kubai6@1{t$Qc7 z&VIJ_;^*?Ye?W_cFg`&m9W?MGf1DYl7rcI-yxn;604?+g$G7$Jv(lZbXwb6p>X-7R zr}TW-zItKv#xiN!fK35+`OV$UYo9|pmXkM0gKEEOFAOpQc=_4wtw+C=E}q!DcMdHG z2{%~&^;6Xx5H~EdBBFLTx~^DDm<>Ulm(u#zrEh;E*Sn1u=T(z9gqF6Be-nncw z628(-=1#E#gIo~n=P?Gc8k!i{Qv-C)`ZTEGBV?IzqDm|Gw@+OtpZ^jQ!4dAXwEENL z^Yzl5UscW;PWG+aceh_$N|R z(u#Q4BFDw##>*R9e_Sqqwo*C?Ss%CVeZRH*L)ClepV|fjkj$8kE&&2Y(23j|2(oV8 z2SYUq@ap!BZ_CTaH=keLTKj@)kR~KM4>ryeyqv$KiUs<=ZFA-#t<*5}a07RGSOfn>y>l%}c*3ND(1($5vze zo8JMy*6(bre~EX-STN1o-a3*iFs1 zn0TY~YGw1pqpjnYe>Q)62Cd;%!CDkxvR^SX2{(b*9%QwoGEm)Ev{5{LL?Bn+u_65O z-Nwr^xcGE-SSV9cz`%6?D7Nw&0SQye@uq59YmY&=zCsq}>QU}w1^$meXnD?)n{q`r zRDN`tG)!)i_?wU?K=)_sG*LoSGDJ0)w|}^d0~RHg5``uje~S=BP>Rqgr#&51<=~e8M0EEk(P~TE9{bd{k{Um z15DS7b{Q1Y*3Xjm@E#19$ysL@D2GmK&StWNkCqkgoazv$v;u@9w17_N&U8f)y_kY+ z1?3^B%G7H#e-eZYQbYU(@)KR-AkIvS5xG{1?1mjE6|1_aC&lFJNIB3#eMtT=;mThO zRgx8kJa~xk83XWp>Do&Ocu&!gpQl-{q@1Oulmty%P52)Rdf%vYtDINzWFRa`pNvRp zISG(9FuUPz2vJ&9rxOL=X!5)9{MPpJmz&SN{g5w02BMZlrLD(nrI#m4C%?s9>1r!vUqC~Is*?kPe~Q^yI7nHV1xj(% zPJu*3f7A@@LRv~BfPApT=*kGr+-232oXLFVbS!{rtRe3aRU%>QEeR>s3W@;~m}5!> zOxew3a2LPSz?FwvTHW~q3Q`SOzs$USK zgqzpCC|&%St`}Q#kc7}oSC!T2v2_MC6!cU@iW!lVEs3zrLN3U3wsh(RIRZ#2_H*^2 zim4EW1%Sb$`Qb_B_pX2g%)Wjf;bRr6VNz&B1fd}HDxQ$W2wGQ;k74(z^_trScM8x4 zf8-0V-$y>_0j>kxc#t9$>Z(VXGAueK98GEUo2}dTNj>U&a~h#1=!T%v>a*bxc%BgK zM_P6L^w!I-NGk*u_(HRaL#q03?|_4ivUgEm&6ou`8i4f9Wtyz$3Oo0d!rV4B0C{KA zi-ejowJd!J*&{%HF>7OlQexBpQRBGGe~OX6n{?~n3V#gsahvTL#0J2%-Lu(#+1l*~m&(`IHh=y>N&3F(86O)Y_s3Dii)5K5kvb3FAkY?zVp4zV#ery8-3_@xKq?fq8w85oBOm`#dj2UO`!~1BzkQ8& zG|9uqv%tdGD2Dw1&N76P z0*02X7%{Y@sQ%KRZ_p6Rf62v=M3}&MlMr$`!w#o4XlZK?hugwJG-!@E1ZUXZ-sX(j zgYC|UIc&GtZGx5HzQYo7w6|N$p-4wC+F>RY)jpMUozNhey;w#_8(OH;Ev()L4~_}4 zl*oe$a)dCskU!Rx4`xgWF{B*aLMlcGDqhq~Zwj0#L;Isyp}91fU$v4z1DB+<03piWH@xWObMY)YpH;u>>-Ue* zEZ__T^d_PF+%a$>$Nj^sl@+8v#`X*dTTh)MTMjEz$t?)PnE+pZsYgLBZf8wm4ZIR2 zyZd)Tp75Y`U}-wgf7;p#lX|cM6m`n!j6)llpyJtlE(8V>wMs@R z9?H2iWDS(5`=agz8BxU}M!qXN<&fzm&&hw7;{M~0v8zr4vlJz77)aVX?Nu<5WdalO z;{cn`k3R+gI^iE&$>u}w7Jid=07<6-Rx_V&h98FwOri;e=&{Be>kzt5CXmrOJ)p7c zP?9z%=fWV1f6+BTp@@MXh6!p2v#Wtgi?9JTE~L$KXD|{m5ZWN3%jkiGM6Lt$CQkzr z&PHj~16lhBK`8nb=Z{|6^*t=YEvjBI+71jJ zo(5BO*1$m9;N=3W9qO@7CyV;{%G_-&oFuQbxx#7&!(WWGj9nd(($0Rvr{XBhGT{g&`m}&c#d>-GS8Y1Sp7ayAt7WAcV{vZnfDI_ z_o)yK+Mz*cW>OT)5iGeh&kwDUa8IP%v$0YY#NJi_D}vtu%00>daF zE-ar&R!F9$OfVxt!ZS(D11Cgq7$f9+kCa&qe`X?$#-J8b((isiD9+)XiYjgeur&@> z0?Sw{%3l2)T$Bj#pwW`k5G&R*rg%(~ouc}k*VrgwLyviGOf- z54$j3@uYIe^qY;QOv{K7LEClYL~l4I6}D<5uhE*6-hE?YD(h&Q%_>5&9b3n}{nmh` zf2Oc%2Gjbesg|kOU3Gml_PFiT_F>nl1E|`2jo}B-0Ypv@1zp8%!dv-^sql{7Mmhq>}vzC)l-hi zdupC>+|XDtJW%S-v96fL57wVOa{Qtmld!4bY=VZH#=Xe4;A?F$21fM;Q-|#Zf18i` zg9buMi!>mh^gW}SA27PPS3*zQ0D6fwDD`J*H>1YJaA-OLR)%HjAaF@Y`$tZ z0q@4*i#he~Xi`SA#P7LvTC3Wa46gIDY4``o27ST4vug?Hiy>?tTtT?x?0S$`p*;h| z>g_ycnsj1Tp~`!oT3UU_UMf6wcQu0K&dmziS-xBILa0(>v7p%xsZ0yf(?arb#h8*!2?q3)r?+O%HNy6d7M{BkUfioi;=TG;C*N z*iQmHP*)CgaY<0AY}L5Pf6KiuI|MY?6?J;O9=Mu2cQY?05_@bPs?=;)IsU7SnweH& z2U{RiG%>-rV&{2PIe+mn4QMe7x><-t00zX=fKxFOP}EJNUQ8g9t*m}B(yR^yZi%EW zm_n}pUuwQ~r~LEnsFay+K2)XaQZ;1;(D!}wsLH+`j9ss+SxOfkf2-QV(u0d?HC4A* z{^r)^>LXB>QLh6|Ye7c>AqCFdg@?TMQnlt5vKIuXl(49*Qu85ZfCb^!FRr1wM~q6OWhpJB zW>XT`c5xviW}6SHe=iRnHuz?z#(cwrfy0It3oa3GhSDtfC9tKDW~mBk7PLv5>#yi6 zUsaGplrWwUPAJyUIX3_|$ts=Y6|ZPl3z~RT&%#`4&(P$0>yO9f8+SYD07MD;uxovQ z@u60a#{fi7RRODF2^yN|u^Sq7kVaqrxOsjJR6Kk`1QSZDe-G)?)rWj1s=b43*$g4sgfP<39%QRh_1C}JMkV-utfd752YnO`CS>6lP6%0+ zoi=X6eOsaT=ck*01(OcpCSI;oHKG`CUL!EJ98+K~J_J}d z&-}dk)0tXuf7PH3h!N;KK-L%MoX0HYJ`};AT(F3!mRCte3?t65Lr_^H($>2r0I$7& zZSP_Kw!Mq}YyT7XFWtd-G2C$rgB`JoP-s0uRpt%QOD$NTcvjZ>R#&U4qs<{1 zk!oX1hLM;BG*yw4{H5#}!v{o1tqz&DifgiJmb>-Gf0@$qa~2W5u8lFBsm5l;bUo3C zh@ImU2=qlzk1li>DWABxc~fyZpmGh>!W-R0F@_T}f&ctbdHFcqe9TH+v7`Z)iC{L9 z-Td|0#`EWZ=r>M*lXUetuK$!+p0t@r zf2gTVAz!A%o&j|*U@j7t)|1tSaR(tCbAptRJJI`=?l!0jX`*X--0DiSrc*%gyi9C! z*bot;QGsR~Ri?-g59S5#c@*@UvXZis8KkuuTr_Ja_XrXelSP%4=}=}eHa6lptWR8S zK-*=qbTD2q#qya-8ML*ctHVz_eH}|kf1zN4u5=LAy(-lzh;S;W4AvDRWs&L2wql@u zE_E?kfN(}kLqC)qfrU_TNds4fg=UUbmYXI+#PwAsN9i>!B1*wSFw7^I6xPJ!YBu*U zX0qqTKvtHZO+v^E34Yl{!aahzxf5d(AEPP^_$H<}(b8MjD^&IHuEgw>9lb{#e@123 zRf4G9^judIRoVJG(1bu2m?%fZ4f=(ka)xcO5GdKHMr)RA)lBh2hOn}r_8bM_b&gGJ6L$>xVRIrxrMw%-bh}sStp?dpk6w`{3sl>MiRm8DzTaL;lCK>$s|hbFZ$RZ%v7hz%U7 zr<~-vQW^pnxOM=8n?F=(#i6%NV|0DcsoHxNuf6$oowJqNd-si0l~ug}f4SIu7Y&Jw zewlQ1`ZboTA)(e!Sn@UIs-{x3f{y)Nqh@gDc7dfjAy}}>*a0l0!of6fFJK+=Jb-{yy)}?4(sGOs|8w(gGoWQROvni*Q)Uxu8u8 z1eqip3|_$$UXlgH1@V;_Oo&TJVIu}hOG9aYC0q3#fYFk3{)0fjY6tBkQjM}2J;a6Rm>I*G24IwG=S8m> zX>x{SpiVR+B@J ztUzk=&TB0O=CuY8f93>ot%5mdY8n%w2|~s-ZWDC;ouKSG=4oPh3fq!w6VivEin4`N zUd%`-IG~iBs)}Fh1)A4wV5*5@(Z|_d-i1*e`{*mq!VQ@miv&)a6?T6(e5eVx4w}Bm9y*+cWx>@l4f|he?F|6GF+vBLr1_wovtXX zAnr4C^r_h%nA}nMppuq_y=vwf;ujRDnK}xsrH>556N7_wpr(T*!;Iw8vvPA+caLjg zaC~-bVtCv;1i5d9y0JUJjfx&rcAX|(&^*pNf2#c`{$E&~By^~(QZ>&DZa`?@=(8AXo8bpuaAVhY$5 z%3|p6vHDwatD%RqAryje13nD1122J2aW_>hTtuNzfNNh0s;4N^kcD4dgR}^}=!;6) zFLLdrLn3cFO*uJZBEZog0hLlJ@{>EJxVBj;3-KZWrv$$nG9Ev26oBp7$evI6k*^Op=(*Q>;t}=iD{W6fIEnkgU#^42b6dPWdX>D zdK`1~O?UR;)~&at8NWv!DkGrxqn(FP2eMj}M+K21K0AQe5W*d;zjpw!!R-Cpe=cCF z2^?U-+tmNOw*GGqA)t29|Jj@lOO^i5?zHUd|K7vr&(Qzrf;=GtVoZsY@P{^3nhgy7|D_uOxg?qp7WBJM&yYoWyQ#Hc*gKx^e{DH-{md}#6Nvavr|-gtSB4`)+){&o4Q^Bd2vqE!lKf53F{+~z$R z_+{mO>DT4bg)0!~{q#$S2BY+k3(4Y5pT0-_Wx>QNQfgah%ur6p27{oJu0lq8Jh6TI zDKmay5f+bcU%j;X!!wAoNn_rZul)|8)_?s}n;ja4`!OW2rS?jlikNL*&9<**tD|P4 ze<4`W`ZYBi?e=FcU>96Jf34TIk&QyXuyPgqMBOB4$cS47LWw^9ZR^F)7-hD6^X}H# zKOjarwX0G$Pi^#7QXy$?S*q0A_sLrb$VH(8V?fnX?cNF4OzS5Vpw=&y2#rD-N4FJZ zn?RGXYfr#+2;obb!fVc*lNgiVCA*gmDjX(l%>atdSIWvwh;5HY4QJDb^S znjm-g?e)_71(rUM)`!!C ziatqYe@LWr?zgSSzd^bZu64M%qs)zqY=d%07F&B?d$g}TI#wb7--Z5%MZ;K-v=dWZL4a}6|ql1=K%RxgS znMlbW9gJtQ=}wbradEMA(bg(uVkRpYmx+`=e`o;Rlv^r%bkI!LKa163Z|!ijIodm{ zZSCf^cBjE&c6PM3*=_CZ7H3C$o73VvXjl{@**NK8ioe^=%7dm zc5{dA|2brc=Y*Dwlm%6drQIA6VuucXOz7QT|E;CPK;UaZd0?kd2*X7?6I?X3v_JtU ze?vG)`QyLJ*kh+!%sGSLc)QZ#x5=(;RqKgwmJE$v4_glaq54oA!#y+iXI6O-NTE|;&v<#NrF z|6OjMh5YMt+FY(7SEEl?V7$L?bSCEVecdUyo3nGY&@jx^1qg+#^l} z!^vSOoAi6*>3%_;?Dh9}d#3ukV)9U7I63B(M@N@>d)hL2-?Ys(G?EP%2L)eGTZcIk z8#DKs66U33Z)l`_KGzWvdfmRLf7RF>9_UH74@K-9-Tona@613T+at}JdMs^o$szYh zA|wxVPmL$%yy32)Nl$FZJT{uQOm?+-XCjf5vEYbVd!ikdw8Nbd$9;W)g|V1>WW+Sn z?z4@gOjFbD>4|aofHWidLo+eQux(+HyzQ_#bNR3_)Mbz7`ut1cxIZRJfA-|)aM~qj ztTubNccEjX-ITHC!Mn8QY>sdq>onAB)<1pe;5&pne5m=wkoMUk^A%-l4e@v*i5MCUPMRE&C zad_C*?H7}C6H`ek=Jj{Gd_JFGZg))2<%h%J-b8wCG!<%(&G`bh-eSfg4_~W+x=K*zJx6EOY7LLT16zJ#JdEnw(Lism&BmcA1J3ZQ+?hSH36WPnd(Y;e=(}zc6p^ z@J|%dd9i1_W5AQ1v(5D+{o$ddwroeVeR67gJ{XC#h5TbS`{+VpxX)&DiFP+3gkF1m z)D;?)XL%sEb2E`C(^PuU7LQ2L z4r_8gECs{u0r%pZE!OXLdfc{Pu(+@k%gBDOI3LKkW&oGsyS^+#ioq|sLl`SR{| zWB+)MOKgizn5~X}-;y)h=P8Wl<|aIa$;n(c&^{HL6O568Hjm2~jHdGmW5;k&2+tSW z?U_M$DizBwe-`?>)9zr0YuxWO4i!>`xuI|<81Xs=gHzs->Ar+d$jRfGOqYA!)#Gt3 z4TT*O<%la7Z!>ml zZ1*e>B0T0xo5tb;No!!JX!bZf{i6|AU&KA^_PKq@fnsmYV|UF6j%mx_!01FY;T|?x zhn!t*>tvtgmQ4e`@L1k6Ga5}fL~}xp4A}$eMZ1)hik_5tA`#7sh0u@~9G|yN4;1aA zmVm|Ce`{Up_qm;^fr+HqG%_C>a`xK>Ow;z@lDClXw+sIGd{XcRGG1>kKiuY=Gqz99 z+Y8Ci(t;@(F}nf@w<#z_^D{Y*-Hd&InM7E>D*gI#= zwY9g;**iv^rmpee)Not({7AtmW|zj?@mMTAHGcyz{@?KRG){N489)L@UJV{mXGGiIJ{@5pESCUX&~H!CjM ze>-Ab^9dn4p6Q57d2^dLJSQ+qg^KNz>>-3$(X!TPE+?-%H&PhOy2RR$!#&2I*R75IjOJDUN8<> zj}Ihzk`puGfSB&>>K#h`2Le;jp;n0l;JbG<@rDAMH!ib60}n2On_qzS9kYnJ-# zQ}L--G}G<2_IiyIlFzr`>kWtP#<5`5Vd|JSwHuQY9*@v3dOdb|CYbIkbc}XSTfIYr z<0Cn5XmoByDoTNl=~$O1Z1MOf!rjrOvB{qP@JN4KAR5e!k58w%yVD&#e~Cm}DCsHo zIO4hKE_2vAJYRHYCc=q@o-V&R>Io+z$&|aWV4qo(T$(+dlIv3YM|ddOeswZ~_s z@?v_>XAjH;jgel#+8s7eeb>P>PJp@1Kg>hJ&Vzxgg1@fu8of zTlA&+`jTdAS2B|vh&%fSf+oj6q0MFK?seM-?Xi)WxuC7vV{?oY+GCT+boWp+Jt;Yb zfndTG@pO&O+X!=($#zGJiv@YaIX^uR2^$NEM9Ob5d;C%+?wAaUJgspup z7f6ey^t`z*Ff}lf9qTKaOjF_E-oEZJUosXJ(!HLJysx;_I~K4Q7oz=z>GpwOTdy@% zATyaKTYJGh=TD4|e+>ot#xq@Ay>h@k=aQY4>5O-J$~+hlvIB*9-$HMnG(0};FN&67 zIq#q9NC!q{T!FUOd|@h^nJ_PPv!^0yktH&6P&18M~kl>sN4Gs+CrYytZ_|kwQ*>4$%nk?R) zj*;HsrQFoKF*=p8yZQ&^-q3WxF|{zAU2^&t?ec)he>y%U#v-HLsevhvf3eTk-{meW z_DqF~rlH(O+TC4P>>V#g{6?eO)?SSD1>%yt=Tn`TBlpOj@q4aY&v3#%O*#vD>OJ3Fm=tRdQHW`(Y(Gebw<~t$JbNa`;rfy-*He}CEO_Z*D0+e`krtgc&*2HRk#MDLRkkMxiJQeh>?C zS`tLg8Fpk4IU~N_xM~(tGq!|y@1D~wgS@J`gKC?D1S#{f%i1)2lz-$#<8#+BZ^Fku zc=b){N1E9c-2S}6!Dlz)pW9t!$4l^Gu>KL7fYTd$PFZsyfX#mts ze-l58B0y>As?tFrmM^)55Y~gW#A}2X=R$~y6$!hi40>5+_LyBhUD9RG%yMC@{XHW}&Fe;qeB)pHtA(r97$&TfxUVOItj466;GBP@q=d!C90}#lKFmn&rQk@T1NTdG4 z&8-=vLw;fk^WqCNs*R2;DtGVtcf_XO(a$)50Q_U!@g6^xJ6RPSpZ!^2XMV&!e+pyB zy*b^$RM}Ojgvq}|h|(aY%pnzgmR^z*`50LZAe7;$q~8af&_O`a%Cq)g0dzZMte1!X zVsw8OoLeHuNu2LyU@-ARGuEW!FaOq(rhm%_^@SYs-D%%Gwr1LAc<~RgA5*oes(jZd z{b9KpQ;DezvDxLcWgy!I=$Ib~e+s|ixN)s$@G(hz2$zrL(ayD zgk{*>D1)kMne85rF@2RWt^+mBS1-W6n!s^cMB3}dQM=lGZ;?vnJJStcMkTM*8`s;Xw05-1NUK?dz+>SW%nAE7JO1 z`|aNGYV^JlBYZaRGG<|&jjPOSPI`qlHMX4&eh%wb)8N^9-@}`0l!arU;r)rD+p;}H zyKkVp&FkkGwJNuR1T6xUe>)s^__E9pRlmkK=-CrRdFVL}M<+JJwmUfU5>i2nKQVIQA(}THg-%f1_7w&#cDo<={ky zJ9z&Xj9xfYd%~_(nrK{6GT2gJMu)|9?pL5E{ao_0{KUmD|Cs$rbj6i+F2D0F^n`UU zOXFFpRv#)i_unIGCO9Lh>Dq2!Sg^xB_Mbys03A=LHSnxj8S+twzf8wGImio$3w_6i z+??(t{c4@xbpG1Be@!f-_wUqB#F zccUaIL=-p8B>o-|EH;Gl#L%C#lnW76AIw2l&m5ClXsF_2(Kd`MjKp^kfXb0bq5Hyi6GP|24D_2tT|BbK*>EpaBB$MuKVQ4m zu_Fw>3pxsTW45o}-EOg(*iqJWR?Du>H>?`y;0`_I=(keY?KDD1F0UJ7Pigot2 zr!5Vd#h#S40jd*>=or_RcjUv}%XLn)#|!KH_z}n|t%@%^VtUI9z^vb=3ihTkrxzNS zmYZkSe}@mb4Bh;D9ucy=ohWK0B{ZnJ?@xq$6HEi&gi4P=4X++^*+biclDN)ue0s7% zgf9Wz$Y`JO#7Fh#v#;St)b*z9ShbiD(Kgd+sZXu?i>&b`Kv^Cnz8W$z!vKGmo zuS3Sixs~w{X;xecE8_Ki%^MsrvYA-S#t1~Rf1ubXUy?k)^XVsibByBLC+Np-Z8V5X z@0WKrO*c?3Dsm?xB!QcUi$mZ(+I6 zpBFh(>9CZ3%_oZ$Zyc=m{$Z$;z82||BXrFsTQN9ai(Tb|BUUgj%r{b`K!^n;UR`3( zf38B|yfZPL_Jem0DKCYe7UoZM(U0p(i%NpDp`&@0{l0$Cxf^5dcAon3Q9f0c2C;_( zV5H%y8PJ|hS0Wmgk4x#=isTC01#jljyF}txm`<4O0A)sA@mahE3XuU*GVg2oBr$e;qF-&GUo+GLmO|EK$MBf2vvN1Z=wzhANQ^{1LH^njz+LUia$+Y!H4nhq=$TRWMLb z*l***tiy7%R+zio-78|d9ktb5KdA*peybz_B5Ygz-i$@fYCXL&+m|0YPNWA#!lIC% z<|p#Y*5&R&7xm{zms#h&E9*$DoRs#ax9Zpq$qH>h8-U#N{?Lrj+>PyRe<1S#w{)DJ zp!L8EzI2{U&In%FH)g3|-(5S415X*E9W&%qAkc zo2DzI*x+Cz^XC}IisXlr#p6VbNtju~UA{*%WnHJZnR)fQ5B=#ri-g5Qcevq|KA)^N zGfuQr$KpSWu>^3kc*Ot z2AqB8C*QIFG&JO{mJNc=Xdwo@GpSau>u&Z0Zo4G?G^iWsQ-O zSibL*=~rH!&|Hp=y4L;$`YMx-p`2b1Fn{YWrmd_C00m}MDMr+A&mu-I%bwtDFWG-t zg$4vd7FlZ*B)nh*UrexMLXN{Z(r*GD)+S=_M9`u){g&%ll|Or&m= z3SRkNzA}audbY&TH<%zK!Z$>e`R_DOU7f!BfH-g?3vgb4UNQVEqZHw=2Fp{Rl4FrQ zJy%)K2>TJt?6nwHnMT0{F@VY(EUa(aE=JWw(Aucwo(T^G45pgYh6bwn6ekImUk1)z zsRp0ZnXEPgfB0`y<+@@Qhz#iCkDp4AFRg^14A|zlaLdzW=sjC4-sjU9mdvs&s)Eh? z48~yE_(wkDrFGIDLK9ILG3!T3lz24C)>@|YUAWTjaEulY1r$9^)run$ZUA&Ssfug8 zk|Rf0HR+iUylronN>Vmsj-2GmeW$+=Jj39i>0_k+4FAVrRz&7f0p zojAE`Nuh_tyd`b=%X5t(QN!#b83~~hjkSvS>!hNyT@f>n{TPRCI1)u0mW=O#oZDv)E>7sgoJ98eRgK>_Xa33VJWwd?Rx zI{q8~Jxjh!#A#peSx#;c-PO|J&($itXZ#p#n6*K!f5p{C=BV(rtRqj2we9me_<6Ul z%RwS47sY`O0Xy8sY7N%R%1PH8tV3#R&@b=4QVTOyZa2T*D}zx)?=HA3@x>)8OgNJv zt@}dfWvKO_3#}vhLUb2`S1J!?@tq@c#4@7N)_o{=;s0T+cq zhA-b&e*oGe~7Esyy6z0Wt-;>fxT6>|GiGp=Xo8s3A;vQD7rRqnx}V%OR=es|%6L?(M*sNHJ1a=gnc@N5>p^Q`klX>$n<^S zkkHxzgOb5Fd^!0Ru7rDVWxYp3E@Vk0V{`hP$`$nAWl6+#N$cUYK)aiA+!iw)e|O>a z0}k{QCuPv6QQZF)Tezm92MgR-XTojO;H`@0gwGj}M2|K_@u0JC zA0dGME$>XxA`TB3xm{q|g#n3zV4)aAeh#k98wEHJi=WVu;PbucuR4#*9vf4e> zTs$CASTdDyD%xq7xC>6Bx9em!?zG{>gi~w?!C_f;fybJw?TxwgjyIw9jE6ecAs{qN zjCwlvSpq)Xl%-6gS5AKH1=G^<)&m6|_;Q0*@Y@sJGbv6?QniZo@h~DPe{4saDnf*S zdPZf70O7-7D=m#rk6RM&?1L3hFR<^lKAs5HUxl?;8)_#ofsqU;r(&Nx#;N(akZ*Uw z0TAoS*ylx;t6xn>F(pW9?3i6PVZV`WwuAWbVLm_nC9}e4D?mMe7zU$sj0K>2o@wv1 zv}S-9LKDdO4#SegpmQZof1G^)uIy6`G&rBYJX|$O4CS}c1!3YH8)gecZl?v`8J;fK zGJ@kr>|MTjrKd)y%q2JxNwdR<)r+*gDxcX_Gxq$BGI6479Yq%W#pu6%qCkWNZYn#C z-e6G&<2^!8B!3U~o>|emfri;8Q*~4r#oZciX6oWWj<#h)aOG)we|i8yK)t`i&*W1t zTya*N%%as3IEK!nMkd&8enKE1dSV;8UQyVGAReeWg5nD1Bv(o)(L|IFAm`c@SR%5g z2*-pX-vs=0d+gmoUa-F-nc)M)k?~3y0?TJfjNp_(tO5Og@9&SUMJ`*~-ep2M*Qsmk zYwyd5xs*L3_b#rKky#uGLkJs08_NoFQ*(&y8JA3dCt*dv`OZdx%guua`i79$9o zqC`psExxm8xid)lf!Bv)hKeKw7z(-14+!Bws;;u8n!Vqb75OZx>wg+YKEd6c6WzwZ zv^OWBpxUd)owIUP6%a3VlAZgmQ@iKkIkaj*&}M2KMm=5F8ZYC9JB6A^;r9_gZJNE) z^7P+NBlr1QUSE5(L`0FTg0sFN1JR1@j7F{P!RLM!Q4BeBL6Nl`>ZW3ZK_8C$;)J~* zKFw;8BSu?oHv%tFP=Ca9r1{Cf!-&eIB~~n6^CNn8=Jn+Yqq;11qG1k>qQf&WPi)EyT_4^zW~F0*j`vt zMj|}1#93eQ*ZjV^@WXi6p*R;IX~{Q=|1S$_-hb^|^?lLDtGR;xy2P3}LXcZ7yTi;< zg5qI8Z1p_iL+2qX18>VnL_t25A??n>(3#?5a_7xcv#4Y)6U*bx-M2-LHvWlC;w6y~ ze9)tF*OJby-hU)rsGSM6Ar(6{V&A-?tgpDwN3&o~iC>%Q&EOlnt%>ft<<5_gVS28! zpFPr^;P*AQT6OYQ9=FuvKVOzV_R*`;rS-0oUp>lAS^%f`-sBVpiwv(OW)bzlb)C}T zONQ@OLdMBrr{3{H2U45k%a(5~vn?oK-+(ilP`NI(jDO0d70CVodrA4grHcynIH7(B zcK~ch4uxksj}~b4!fvm8C4WM}HJ%0gi`QX#Ij2{b#I$96i3H@zTz!EWZW}ofR=QqT zm;q^K$oSB_Vg`(e9RTg5CXEgQFnk-`HfrfIywHDfVde&P(ED@$f%A z!)a@ZUYtdD9rY0E3}6&)ja!ldApO2tAy69>Nf)=TypLd-bW-SBL@m09V5xZ7{8J{((&}+$GW2DEo zW|m#(4olmVRxcvGSi)YYANoz*tptSWA*y^QyLZea^G+Gh8BIzW-!qq9W zQsS2)cS|F`=tzq6_-#Ul-!bPie8K zWj*hr{1IX`+e_(aguxR`F~ce zhS&G|!uO9(4kc6i!e&dr3O8rU~M52Eo@_jiYV1K@)Y}y_G7P~*((TxC&Zxp`4XIubPvt& z4suX%=E~wXN#x_p1VW0es(kP{a`(gd{&0P!Bm6|?q!?kRNm-v6Su>nnq>kz@7}C23 z+V$?G?$SWqNpYEW>stvt*1q(76|Mu`t7a%V;m5q2^)m9VjUlHeu;G_iNPol@>CKN9 zt8e>-Pk!}i2z=Pj%|EE~2qneA`je*1(_%?O`rpibPB_n8JFy$n&~lyw%M)B(yp@;> zAFcie1pRJ#Re_W~2`s~7;8))%6Om0X5dOG^nxa8f_YcF>%HAK!OfZ_aA;!B2Q_?Q) zRSR^d`c`%K5&T6Nr1)2YfPcWg0SZWG(#rP-kmFz|K8i0RQt_Id@O$8zO3>f8%5Y=$ zv1_I1l2V{FUJ~vJc$kY32rJ5B1rq6E&~ZhLud%+4Q(}ns(|}I3$DaJ96@2l)_ukMK z9D)E|r8O(Q*320zeYumb4e9TA`D_mE&kBcKeDvx*f0!N0E>b$M!GBFUaSs}KX*JPr zyN=6QhRNIS`kPDBxWtI&{3`5+W$>F<79-(2+smWkj5~Mj=22hDpJFpCe3U#p5M@wt z5MYOVQc)ob*Sx`FOyg+rfX>`_v6d|)s>koe{I2{3lkMMI)Hm-MW75)|VjHWV+qEX6 ziZVGQrO7iRRCY;8lz&kRZYm{K^KC@yT4)|Q}*L4R1SLHp;1U%c1EZd)WSfHMAPLHiR0roW->BkqeLcMELzB$W10!z{qj zGF|}YjxhI16)$$T&8<%QR?r$P`VDVQLLX3JV>&sWYLpeBKd@J@r1*&GqyOyEj9)Ho z_otEkx?kg?g1Nlf zzqQGd+1dP@Rxl4n6WvOpg#vz6-Yq_tJU3Wf(_iezHefBkhiA-`3);~SA}f_y?D+r- z^AHEPNs1|Vb3FGNE^E_yVou`weFT2mL2Am)qklVUo%;of#jncFOmpgeurlR<4=VqHuL9wf3Z3P2mL;Eyz>n=WQO=-*n!VN4Bj!Ts|mFLoUpt=%;7W6 z!I~|T6)YSxFCJAsGj8k}Gu$OgHuu!bQZq>X!E33wxVdJ8TFw|BVZ%$>Yd)(*fRjSb zMt`Edwn%HdKJ&$}cgxpto}3sDPiBuX&SOZ7Tkz6;N#pP}nbu_TL;s+R68-O`A0|W? zy)jtKY?hwoLV?#r&64k|P|vFjmc4?|htRVVW_|>4jf+rVTzN9AxM`U!0$|Nq19^Rl z_b+2Dk#Iws%nb1$I#Ls}OhMErHs8BR#D6G$J(jEYjv6BX46ENk$tE_(x{R4$y~`~@iRGsZZVG76@m!ufm%-*J2>v|6D6nNrw}!f&YpYJYt? z?^m$G%;Q6Jv;;U7k~PX<3wQ#+$vSYC!pV-%ma}%LBKt{i_xS*5^=!^ zqz&8zy@9B-4+MB_08pEeMIKB{CEWt^0>Zs}AOW|vP*g5)%?c5? z0<(}S4ng7oD%6^?h)#-Ldh;fs1dX334Gr~9ENd`+5lF(=TDagISo3mIgKo@wm~AT{ zsAbX3LG}X&yhD5Bm4DTmqXtNdU?kc!a2S_yL0%JoNoWKJ>m*D8+nBn>LRO1^nAY%+ zaiNZIaGKF782g|>_J`z1M8Y>qEfnIXwQZKJnSJgKeZII&^GP>^wBA+JuW${b|L!sm zh%OlfWqg+$jGs}%9~@%hpWktzs03aS$YH9)3ev^K)#Yw=K!7_9B|P=D?y(y;-#I&! zD9he|31_~~0_ztpFB}A*f0Gf2B#sA#=N6K=QQ!_JP|EMEIow~eA!$~4JHk{zP-IV= z!lwg&L8i3{X$1t|xnQpY!a#~jyWFDpnF7}T4Iz2 zNNwZu0kZZ=ETjRD=<&*pB-jep%1u*5-ZWAmtxyR-*cCZwiU;2B9S7#!ZZr)!hw`rS z61}HGZBtOH@Cz7DqQ9w;j^HvSj1BnuWqxxa`c#vvAO+cf z(r|*FRS+$NC6p|m?_xukDA56D<`V#0fD0TJylz=alr;qx-W_Zn*#dY(enA`< z@05T4km0jgTc6P=nS`K96Xw$+sb39J?V2p;YpgGk^Y5BKDn5{if`IlI>Uvmd??eu{ z`lZLmFeLK+ES;ldw*olfM+9PlyIc={x0I;|{h&UpPffXk>zxn+bl{rr>FKB4EbDZ2 zLMUiXM7xHbgi6>3;8OAcjQ|ZABzM!K zJX7H>|D~mlA|qbCA{7!EH7g_u?(hIk-$=$5(g#0!v_x(8gtnRQD5{#|Oj3(~9p);s zdEyCl9Upy-a7J{DmSLOFzy%2<>+LCC7=!C!7a>@@AjGJ-`G$1}+i$ZW$6L^68DXzx z@a^@))Pe2#XEn2`&wk#?SU(4%K`L1HFM?1LPHiN^f@6{x#rO+np%TqmI+#j>dmO@x zyS`T@{PB;bn_el#_k0#kBoJwTzz55!h!Y$B-v2*)k~4Cq$i7Z#G@D_3Q<A|FSy9j)toTHRYr3F*%Yb=5SN-&Bgd3Ku381&HQEVgB_%(Qj~M^cwj4> zLlqLlLlDHOJ80^SUb>2$5L1R*%e>-PD7el+;&E?F-7e}4W<`gwcI2vN?~IS>AP_#n zd`T)9#7l5}Gzk(>G~70SJhuWkpd8zI3-3Esw6`+Ua0-R?zUKt-9 z@V-%`1Su>eVbNj2!(iJ6e44Z0MDAmp5En|mkg3wL>xyGRyc7?okD$6ySC(u&uFMjI z-&`!_#l#i2m#$6~y~2LJeEY=&{L@g%>=$YD)Gd&mn|C*us}w+g#^aJtouPSmoHR)Q z!%fDh=8e|KRja`&T&QKWv`68w`opXgr#R`?v~<8W0PLqW{l%gDkU)}0ilns^T+zH? zOyK>996C-3NMnSGz%mSQIM9N;c{2LEidRxV_*CBaf{L$bT;HIsAH5CF$TdbEq=BZ%%MZFQikE{$>$^dO?=gaavQM%5LH+-GE zPvTg{eKd$SKldn`j*R=F0PM$a5Nj^XSFm}D!5cK8pPPePAkg)(rDJUJl z`f!G(WkA4z^}6v)be&xW`{?0VleabjF{FzeLCLxSlHsfcdoN41NA5Ib{{J8c5gSj& z^q*Kl8x8w^RMrBYkckktc@DW&b8MZsg47=rWl0r4Bh(7VGfEEl!+)=gG$>m>HD&)A zzPvvIH!tFb%WTeZbh`^9eGgHEfrZ?xZNiSr&rjf4c*IU>;NMXs{Wtr*`Lg?Z7n$iN zBJU#mtoK{Js=(^j*ZTYvQhHi3>kitS$1;t*dC#f zaC1g|C*Fq9;)GWVU}NljRO}Lnp4M?nm>PQNM9FwJeJm)GQXbd5`O}ABJRJ>|s1aYmebVSbTfqJyWqlZ%&_}xck6g)5 zB1-xs7Al?oKrl7UJ_@j{?Npbz&U8-X(`I~sy5VeG#*Lrdx#2j=6SViKeyeyQ1jXK= zSu9T+Rw=?WoP}}H^*jvM4iqBzDSpiVJ1F5|xZQ?cX7opqL3mV+I?4cl zy#1Q@JruU+UBdoW!+w$W)H)MKSI>>#U37k~9sR^argo5mK>3d+j3E5l{qxD#WtXcN ztp~Q=uj@Qh=|q-?|K4wTpt6^QywA?+(Q#8neS3%drOfebl^f808xEXzu|S{5bU$Gg z64dOfv|m>K(-*9Bl}nbb)TQ6o#BSq%heXljqb40|hVSF;<|up{VD?=&rfcLo?c4{V z?4Nh>MYHM%Y;~)BErj@pYlk~_r#q2(EmAxTF6#AnKbm6yZkchs;EO>h*5D5P_OGNEpR`bu|G^awq(}M&;)z%cDwnx(y@% zqZ;G|oi6&)D$Yz`NRGgFj2^lox#8y9^TU=OLmz&j-$gom8m1y^yXQ8>SN(bYrZP_3 z&s0JRSFNyDxh0>EsmCGVIbVN@LrM*Wa1u8xPDiz};vrm%p7uMH#l1LxI!3;IB{XqW zSxqPXReyCNvir*%lZ=viB&*G^zn*K;iymr3`!gpdy~g`v5Muxll|>DYF#;VA< z(~H8=c`7-pxEWyH4ufI{nSg-y%t#j*hGUX@v#E7NLZr-2HS!XkN$4PDRa#vZC^Ycz zV$FCPUkqGIUiqE9QeIPkIfy7ysXn2L^08XG1FoV4VopON@_Mb&gSgx2bH6%G!4QL$ zaJf7S4J;*QMh|6|XB2dWDA zw4c9lYW-nlRujDM4U_HwqyT48SI)u1C=+s;2BB2YxpZx3M_Sf@4J=ZbpwYhO&jif2 z#<1bnIuTPvy`aOp^cDCBCy6noqX0T#*9?5(43~l5x|qntd1!pB8kopd+vZop%di0~ z#x=^d^2w@2pbihImTGaDd%#Ry)Owav4zG`4neiaag|0c7yy*Az!Z)F&Bn#lLU2B9! zBY`?Dyx3bU_`M{5|NOsAI3z6tWUOU1*Z4CqNiKfzyup{6C(8Ecgrg=Vd+{vNP! zEtH_2RW732Z1@W*=f)Op1iq0OD!srzK#?-o^mARzYBgOEE`lI3&@1ex-z zu>4LnP;Y~Nr*~IrdZu>Yfp59|krOk06bZ)15(R%4dydKE86i=%}V8Y5LcjBY?Z2{`@&dsNa2;qE9A+B#XS% z1CC%If=#+u$7^HVqux=C4*-#k*4*HAJV3UO z7I91=UL{S8PU!KJF>&;9$sktrGN&B2h(L>Lpb42+oS<;u^9qn90vZ)~hWN-@Rz0&; zM}?owjV1|BWwi~J=vnf~Zw_8xsYlLacjB#eUO zg8CbOppL2DU|mt%T5{}zreBgUOrMA3J@c*q50*J12xg0?t#v7A_vi)M_{LzamLv7p zuX2|j_Y>^Q)odhh{omfx{fjznB!+=ej0zjjrEluzo`V{#gI}o<+U2&BHRq##^$zir zU2#TT3oAU!zdMe<2xlVim#Jiw)qg8HBDqw5Pw4L90P0T6SN7a(9IVvJ4I6UnC6~>D z1#+D@w@9#z9Daf-f^6mT9lh`;@bZAO$bcg8-ViLyUaEFr_EIKMZKJ*3=U(+t)+R?| z?!q|IyM*sCi+0htsz6zy3H*E=|J=WlaayF19eC|vS#+uW5H6pFZ9UceWd*LJJt^FO z<BFi5-2Mo7EzH}r4F z9*w+aUVMGvC!RbwFHqbE8-+$ZO7PDyPR#;=6 z<$^4Q;ErtF^+Fo!gL9%x1FVI2e?Gy|I7`LPUTnroQ)&Nv0 zKQbKDG-(kc1EU+6#|{wDAk%MFe&4L!+10izokw9 zQqhyXtgG=J7X19~-$0B$GZsu*MgfH?)FcA`^0WlkQI=6kx4ZNho1MmgKAeaw*|Nf* zo0JUdvMs5?h!gO?1p^HqueIh}76Q+@#2iLcO+U`>-;&9;Lv5F`XH|hfS{9L0&*!{x zzn0?qF;BH$_J@cV$-Fy%-@>kWRn$`V1;%uu<3SEkPWFb6es)HGlwoG}-`Z{!g$s^0 zcYwv-9m_BJkVv#1K5v~f)D0ybbXm#f8*vWog~? zQiT!=OS_>^!omidj})8V?I%XiX3|WI*wf^Q;!B$td#x}67wsqCDU}t-!D&8_oaJy3 zq}#x}Ce02e{*|QPRXot=^Cct_I&a`fh&>Cmz0SeJ%z8wk`7cO)`Z@jS?Jmo+U@*Y8 z6Ocx*h*&Lgi@0@vqC>ZX&-XZ@0p&QtCmL@go3!5Xhj1kOI2(iEasZisAPfZ_Pi6=* zpUSuJm;pWa87jYq%pAT;Kk?Erc! zUzS}SbGD-RfQZ;ajk|BTk4*fAW3!S^-{!}+V36&{uBPXDR|(RXHM>j&*SN@Mi@dC} zw9t*P0R?5ex!);?y*)!A_SB$Kcm@U~{(Wl(Db^H}*F~=NG0t?}2o`(hmlYvJrbB{4 zNbr;KGunoKpO4cbL4&;QDg-+7P?P|m^jZ)p)kkTb(Bj4{v-*J?;f5N1QL<(J+%OY- z2*5JFF!x#eXiqx$F^i0t={vA@C@2Y&VmQv&mkrbRa#@9+wRnvFZAjuB=RB|GvpOPr zLb!XB=lDV)OVlHuwfTC(UXf#lO{Zv6HT^COP7fu2V3BaewnFJ8GB?A4tDzErj;xat zHa+Ggn&`W5OvwqgZ!u%MK>c?O4DtGypXE6uPa#5c@o#uSuXOdkXs@>JWSl`S$G)Jv zrzj6es?z~`0N)|Jn@s*TscBeXc?x%(-a%03C&mk3j)hPe@_GXN{CoOE) zl&1xMDa>R}!Aexz^jvq2VROm;`fKSe-WqOnq;ylH^6Za&!}iS6o8O~YwSD>bs_3;w z9DN&ifB*o8zC6~QMQPJ=DB)6r6M(Apyb64OS9i&wmYONjqQ*mQwg*B_Dx>%$j2$i_fROOm~L)Y`qxV3D~z~cn@h`rvi!;=x9j~5D8 zX-}x*&x7V?UXhOwWCfE7kA8GYg+bYlk!4{{{Nl?4`G(9E^R=MI_BA%7Cw*7rL9GQ4 zdIQOT3l*{Rt0P=8(c{w(H8U=XZ!eWJAfe8g0ml4)@>q7x)Vk3B9~H8J9z&_WICR;6 z*d&bY*PkTD2tCn}mo}Rfb%V!A`pNf1uG&!QgBD)|R0QhxA^@$@d`JU_ z)D56`QL}|j+<3aiwb2ahDlon(zhyjDV^_uI`}rglI&`v(NGlzC-3U78cjxioBve3t z_jwzt>%P~u%zOslVI`bF1?yl);yw4DAG7Z9A=IEfWz`Y_{ot&kAmI z0$ZZ<Gz z;#F*M%=qUkJ-@e@$t&6yW$E5{)t21!BVU-1bzk&?-C_JecmmqGkm0f`qCMBa(+S=x ziwe%9JUz_Weg=a^CIaJ?shtt80XLq1M~qRLHR0k2OCvgR8;~7T8h!CX&wI%Ilba%|J_s0a%vd z=kLDUshJ}?{B=zj^6prNEZp4h=Tf#>pEG*$=uPQ$wW=)H6t8y3SCRc^%`jHI^mX&s zFqYbIkc9SsTb;OXT*^QOk53({p5fFOI2IgvmI>tTOqI=W-_0x(oT{duvUVc;%bK}! z^b68)4~Kqqb9Gt41v>G6R;?AZTRu(}*&*9Y`$oxPU`Lwh=|^;bq3ZAaz@OhcGsWuT z*MXZY0Uhf710B}?tk5>0_5tU%rzGLPXR)hGAuq4Lf{!fvYfUFA|2!&o7UVG$d+#eo zxQQ3|?Zf4L@4($6z8SUMtlX1{fh>B$TVaT?lxGPn7vq=iCj1+J+r3ZqU`PawBVh*_ z->#CG%MdX+C!tL|{BBio?ih$|X0I~A|GU&9x2%v1dE53omWB`OnZ17z0(~W?@-N#d zsniSdwq?4AAo0~b#+j<}GTwd4F>{#gBhW8_?ujMjMf^;ibMGy0zVxT1V+3&8hw8yu zx_VwV3e^4kmX0ZxRf`K1e{mcW!%&o^v8~nwSi;82R~~gEr915BXC90-23aUGlz!W< zR;Q+P;e!r=D0mpKi+;WCxS(JIhvon1n3q~&iCssa}ps}mB-&OK)6O|n2TrbLDVCoVw*Qi{hT!joR9%jQJyI8tze(Te|%rtx086+&!>?ryQPcMzJeq2DS1 zP-3h3&s+c|4%{en94pOXh*YHl%Rsu6kyx;<9;bImhNh)fYyIODPPd<{CTC=5`MD3H!Obh%gYGJquo)1 z{KnO2$X}s}=j-4Z6x?tY4Br-e-QYKXbYdCchcZX}e>tYO!nNH1{y*%LGb=}3KC0N+ zcIo7uE8L~;f%`5WKlRqYo30?ef95DVAG#it2YA?AooNo8sti7{BZ)c6kA_&9;coQcc0t+s-;R~lH_1ijFUpE9?DS^ zM9C!{fBDJ4mbGru*w(4DOA_Dd;L2TrBBlK#l{W5FF<=UN8dOp2;;!Ka4%gyonKrPZ z?c%G($I_1G4{a=G;LuzKo_^G#ZumNzhxx!~-xK#VEf_4-v;gR)1}03w0XTB_Xq`DG zNX-y&-g7&69+f!0OD#9X-Kc$((^YV%4%^Y(&sTG*;fxirAR}Icetz?pLm(tOY)nh!|1^>&Y$6VYOnFjDisgB zfBF3i%rF8Agx-#4%c-1u#uIVzKxOVLnhDv?xm%*q7DAlbzihB+MPzs^Q~1e!$A9to$FhL>`jqD|XRWM#W3e_4V+*)w$Rg`nex{FcbOIlv&oCbl;1St;q! zj}`1U(qc=x+t#m0$Et)yM_tVrA0(Ley%>$#N!5O9b2&PUtxbbn6Kw3a zHGaII4=a%_p{T|gKFi4HgKhr)UYIv6x3Za^+JNe<8ejNaq0# z_SU>V)bgwKUGD>`rF+DEV2x} z{eFC$R?@^O&!k;pXg#$e>8=PaYJxeqw2O!atk2P^aj=BwFxpHGcx_(j@=E1O)=tq0 zpHOjvWq%C{77j$krP{D2e}(9s*UnW7?k+!Sozb4O*4|9b#I#IgijDUaWdM64szJgm zE7w)c+(v|3ru_@>${ekWM$UIAsV&(d#b0_ij`3q2oH3M6iu&OYb?7XJzTdAN{O_B{ zmikPv`dR$9gzy{`CLC(PhUohl&a)5PK|VBub$GZ{r^rJVn5N_o7aVBliM0gEwt}hp}(q&@}PI?XCE>7D6;im-hKHN-kq?N?e>g^Ll?c{V$6sZABTrl3b z|2O1j9D=~)EBem zm89*zYZ=36LfNRPf8h8g%4FcpCtnPeO+Y_{f&H6PLNp_OQSmhPH>=RM{bdm+lSJeI zVlVQiUm2l>C$9si`KAq5n2QUTvmIIpvKoHPZwQ-!3I!kwk^a>P1e0x1_PI>X*Tv); zBK*=rQsb)rVK8w{n_p)Jo$V*~(kuFV5SE9zpK{5>T$~9Ee_9?@B`oM7z4Vf+ zaXHHjkKbesFOuZYd*+AogX}TfIDB`~bvTGq$td5lpix^h@tz_F`LpL;Fd@vF?)ALW zaaPLwb5v-hj8xKyYF9L&*Tz&}=RAI*2}cXxX)rrjiYY_=H-BG|x3NP6#P~tc8ql~b z(eGh=YVcbme^=1#PTgDJNIjN@4{eBB*(6&`R^)V}gB+8>HRI$!1h%LItb#}@ljs~W zae)I=Uw(5vSQ^3M&+=Um*sBx}1+jPKrdgId;WEuTTKdB<(~?Yydg?JAcpKSe6{Q^n zDsEQRkm!wt3{|aFggr$VJjnIPw$KF!D}ZFt9F$!CguUQ2F?3Po4AtT9y5kV&hbf`5X{PX`iRsG#jWMx= znPnQ#lxTeqBvBq}DaG}}l1tD1;L~FHLzM%nmHmWVRo3`Jv~npDaly|>X!KbcCaq4U z8UrNxjGa=k`{h$gFW<9vewdFbr-bW-x4nklt%Q{h=S%RM-$Br; z^r6)`)T;tr@7B;UNIE{G`Mcsh6OHyVb6~RJz}z=ONJ#X>Z!7E>AY)A2`JxtIyZ|nf zV_Z?}mqC>aEPpi=&h*srKg3CF{AXJ?)iI=4OU0VRo2^|$ctOt+JObcXKrJfoA5|y} zs|AQ3U8!B<7@2`B1RvVjqi8iA4+|l8`6(EXD=U(Cj89sL+-r!Abp6@fG4|f<<^+Y5BUvcsCFot4)nT29w{8e9nUmPr1 zWUd@hU4O`Htx&{d0fD+6-NYV#WNfI=#_wc2n}1I2@#bZ?vNQ>Poc5Gs zc^%a9vxW6DfH|nytvgyX|4hXnO_SwToCG_gh5h7 z7!z9=p{TjvHI=G{Eg_X_7nxy_FA4_-@ODQ zkAW^MdYd=YY4)Ai))bBbP%3=lN8!4koP~V`p^^yoZ~)yG`hO~MIy@W|R`!IvoPBXI z+cLe8RIQ`BL$lNu^MxT;Pxp9B=`je30-QhX2ezne`EFHp_@|fcDfZc!Ru*;*VJKR{8E4=R%sy3asMcMOtNJPPCQl zbCvNoLe1m)seid2)2DmYz@@%=fD0;5ABSJ_*X9kaPk`m+L&0d{S`u3k!Ky4L(2 z-+n7WOSxJ|%?nQ-Bi=M0JYmK4(2BqW+52pcPG6L!Flufk3w->z`f1xEV#XRrvC^25 z@w|VZtf{5_Q%70_*;SIK4C8a3UkvwWWf@);pheq=Xn&I}xa9jGZB|HNA}_pIG3b2; z3i=TAdB74qGe6D#eoI?>Db^;E23H&BmB1bxC`MM*mrq~d9qLW!pfm(`ZHr|2h#qlN z=zhjjfC?R$F(C>PAe4_tT2{V$o<|Iw2?6^tcR?V)Di)bdIJz~}%t$kT!NmfIenv{+ z%|Db0$$vb6q?G^0KVJzo?dzEBdkVP$rpupR!~y@&HyY3`0Vg@YT$KW#*y2LpVc6>h z=M;=RwvQ8xU|lK#|USDSM34K{V|RJKVWWk(?73T&^4XHBN053PTK zZM?Ei){orWpC!Ynqt)jF+gl>iKQ6;;HgxJUY(^6&lV|NDgbI4a5vDU^qZD^WN#s}s zl7F7S(Vu=$YVh*r!8b?UazarUF+YwkfY8Xak8K_rZhiTwVezi?DMa(1xGP?0aHubO zxC{>aQia7xM$7wUv}0`%9jCiIhv92qr6zZ$@)?%u=krnC0+1xM5#WOn{K<4o6MRyI zAK2K~GrBQ~HxaY_RnFZ{nbF63@)Bk!Dt}Q~KhOO8OJkUdCMM1g15h&IxB{JZq=rJP zBH0npM?%pAR(L$09;p;=}@dw`E>omT|xQjx#Q2H}jPH?so+^UnQIG z3339+m_NjA_flK)!1q^?OD_)87n@oCygolKAaqbo2A0*WDD>>-p?VuW?!1w_G=HX? z`Fp7zAgmr^*z9wDRENuy*SVkz@cHjFMW4Fh@AI*hazbvdimy0G8##1$_LVUq-$;TZ z;^T+z+hAbo?KE%P_DkUB+|n0&t_~M$>S>YCsc>*Mxk$JaD(~NJ(zDb0qkFr8Tt>nJ zp^`AvPC98y2{TNa{JhBv+pdeErhoM^G|5sA0$o^ie+!NKk#_?fo`624Ueyoq^Q*eC zB~U+R=AQ+Z;kcqYM(X$tqqXEue7?sf{_Q@m9F*a()LJ^g4QY7y;d0Z80w8@txxH*B zb;Ggvt#qSSReNFM%$dY;f}2I`E>#@j7D^!R{#((n?8?m_SS0+6D<^;TWU1L&c@t|{Q(AXTjHoDurU?qoF zegDsR&U2&`96r>{FwuT)19>iURHdITI)?LpEp9O}sG{M=M$?QbzewiMni(|z_ePEa z*0I9<^ZN~^h3qmb#&kLvOSP~_Od|&JkM?x;T2H(N@L6wD$15M-gnutAn~hDoK<#p_ z*ZjO6MoG)7dsN_{UE|wmI-6|lvMStfoacpM!cpfd4DlYW6!qkR5()c|C;}&Ng3fWk zQkd~#>N{c2{)AmEgWdBTEpI*CUyCZUrNvZKc$?JFa(>zX7_KfW7{!)7dPTh=xU&N? z6)h-KZ)=hM{ypL4gMZrI>vHOs+`ksdP;LBmRSMCi6Bcq)0sypM z*X%e5bnQt`f0R6rn>KH^1uw6YdU@h?A2Nejj|$<7?BcPGm4By*0$-c@MzON&Cr^{P zM^&TaPI-P3o!>q{df-*Tr zz@<|E43|6a!`env92oF(NX@|?3pWe)m1NnARPFY|aQK4SW4HN&*+yCW7~MDqDjMVi zaZHDnNrl%9pS@1Jah#?%G9Lt+8U@LHq11_Hoha6qZhxM3_u8ksh?}>ve*8t==H+9Y zW&V5p7}`jdAy)X7l#HY{(r3Pk5c;vK_(f?mRm3j3)cy32AOM|I1(LdUtRLY6$kdUP zq8qeOil7W`D18r@t1GWMJ z(#(J%LVp|(K0ICEl+4rL*FzJ=!@YF>R>uofwWWP=MD0Eg<;2n|m^0(LQ|t{vkj?;O ze0~y~ZKuuN*ELLgXL~qu_}KXsK)e$`KYZ!uWL2pZ0*hPcUCuzX&?|s2Ima zCgI*%^GFzooUOu@KMur?Vip%^cAwH^`DYIjNPlo9+~hKyN@)!zjGsA+0Q7_!MzynPZw*Ic_=WE;~sz zrq$M%e`Wrxvs^wsVf@s6KOPb)e+kX(q z%uEItUj(&EmZS&zj84Uybk^CM7uG8hi+_QcXNNPeA=v{d;4aXmJ)p<3aY$M@XF&JU zHWFhznfd=E(#=&q=2J>}_cUQW70r;YzqCEWAGZ0K@9QWWCjIHq zExypJXklJ`9QSLU3i8bYb(=M^zJC{t>)_Sqow*`+tD)B`m$6s$d3synK${{c2l6n! zjggWmF{9K^W%M(-L^tAdG*`R3%hVHoD!uu`OyIR7w#t;DWUvmd@!CU^_-XeXcLuq`_=E-UyCVkZ*DiYiIDd)7nB9L* zl5Ly=(`a9e(Oy+J9>g_y99ossmMZS6lMHl=6O_C<)bIVu9~OU1dY-R$^>!YG-U1Xk zNPTV+tB{ZS+b95e=4bHCMpy<-AAACWO#3@C$O3^e|qBzc< zLh6J5s9NHjHCqr@9<-v^vros2;sqB=j!=ausQ3$V*G{UAgZvcJk2GPwWX>KBWrb+; zUy|rXc5vD^-y>&=`HbNnmfDALFjC{yuezVO^~xlNBsS@COL}%%GmDRl$LIgIPpcFG zPSchgW!ypc&dW3fvVX5Y@~e&(H-^aH_X3q+tU(#`H=5eSr z<5qjmK?jJJ(0_K$#I{fC#)Rb-1j^dMhYtDjY*sjDu+-YZIcq;Zdt577&6uH&J>6GB z6=XzLb#ID-#zH?A+5k{MufKISfTG2Vm9p*;PaA#P!R9X&Ygo11IVG%UjiyXYWQr4Glss17TdcI*?`{mMfT#a|-a zFEVhcB3p^`U&aNlmfUw9H{Rr>* z0oEl@&;r*X(ZMJJni~L?NB$cv{q>pTk|_>45e3LdLR*6Na*>b5u z)4g9g;V)Cn)cRc5$PX zdB`(Rtv%pN>a(^cs!i8&VPZLY@U2* zNK7B^&Z5z5Q2XfmZXerzuNc*dwNgjAN0}*t?X-`kuhC2Cl8)u{brIB4}M-^-@ z$@snLb$cs5j0$7Q8|ft)WA3(_`GelZXBBU~$UcD3oi)I!UPL0sUBhmHa6t}G zPkLI-O87bZPEIYyh?fb9gnw^xq19kNKkzrVOVB5T*6#QuS>h2p7Ov5E<3zYd(SI=d?X)N^OCrYKB{*<3|%qbCDNwysdfTg4blfQ-y8@Ro<9VUL*QLB z2LE*+syxY9Qh!@rmP05M`w7O`EB{imoy4YB`va@9Z+4w^TN)ZIven)Pp4nX|%d)k- zbtC(=TKZ6+71;aUV_4B*_f_7n$P3^@I(e-}o$gh!3VY96RD11sC&PLNcKqcT&#OOQ zJg|sh1H^&IffuJk5XAcsA+KzaNWeM>be^z})ITZ)+J8GmS8F=i(MToCPVvF>`hfnj z%ai)$#{wW16`mr;j1xA#r8uH@^hQ=1k2Ysd!^xM$Z0C;^czzuQP3+!e2%&}RWR%R+ zl!l7XiQlYfr);$((`U%dR@|G{Zu~3QxIwd;96^X~EPr!ri(SDMJzKR)L(f`}%8DK2 zkq{vwe}6EbNic8}UO#=MT~?%(TGY>hGs8ul=8LiMwHSXQ<2zuG9?Oodw5P3a1ZU&%{=aO#xqqKD9rJ14PsU$t6BG9HD+ABgyoZ}E zjP$!7rBwl4e~92$R>OJnvm#pN%qb?brq)t<=c)wN2z;cD;;d90A$FFXi2yL6)bf74 zy8(U~l*HB?)tc+a@Vqat3J36}hFYbOKvi7`qcFRuRHK&|;?dw+5j_G6BeSkhNz1(Z zlYi=^v%&MfAI0h6cg6)lLicrP_~4$4FOy^=N@D#q8^$ac8?$(>wCw5xoU8O_H~E3zL7Vz!-kCN$6rYrjHXYy(&W;G**$`;GdIN2PC461gRjTo+nmd+t zo@I@@uQ9|S!cI>u;DaEZ1UN~|5az6zihrqiEEE`(UMiCSrchf5T*Lhd)apEwL)6^4 z0iSH!r7ZlC2PuE@%vvLnIh;a1VM294rS&e65&4ri70QJDQen2AAt&z7X@Y#mH9rHh&G3 zxPLS2%PvwD8>fx@bb~?H_yLwA+le`obvRidsQcuQQN%Suh%iL{Rx&u!%G9*oTxgQs z?q1kF;*xO@ka_8X(hJ2?t?QJknKRy=Xy1DLhU=Bs@K*}Da1+NSG3kan1{q+ub5yqu z^bt*wwStbHqx;t4k8eQi)dIGh(0`Cm@bkk~lyzGK7*AswF?=YT569c|!w@u8&^ee=AIGqJ`Yl1%EHtjp0p1 zu$?sDyq#hnzcmeAPp&;dNYr~P{~Rfx2r0F1h0rhZpCTFZhabPe+7m;JBNxDnaSR7M zO)C@#@SGm)C{Ad`Il)9EHIArvxIybb*VR+yhAbJBul~dKJe$E0qCVFbhUtfiKSlsT zNP|Q&;-|QFeRJ0Y)DNi=W`Fi9@2QhylH+0{bb2HDCJ&8ep6ut(?PvEEl-x{UvNVvU zw>wIk&bgQ7E<5{MRpO6+&{!iu+5HR5v{fSUhrBTPUD?l-k1zzXmU0&q^nGOvI)UE8 ztE{N1Nl#dJdBicQnIA(LUV)G`lr$;oWlp$A!tD=1S{uNn8kucz&tP+$L;3WX^^jf0}TmM$qDEZX}#Yt=#8)EWEN{TaZR_f!r; z)b)Ll!6_clL!>3J1Ant7{y!#Mb1Ed6;)lz=3w$u1iyjgfKEMqPL!&`ky_9x9kv+@9 z?}Mj>6(+vL)gv{o$9L%k)(H|XqG7!HAj=p)DByeR{AE$`SufY*Wj5~N_Iw)0S8%n| zI&a>tEm}}prYB|El%YivCQ;SNbSV*7j|l%UZ?1z8)lXPZ`+q@Pydn@jpRNuTvrDI2 zIz8qHuQM6tQKSz^SlN=p-;V7pKneuE&bI|If1?C4G4VN(`&~dW3g~sYyU#f6*{}^h zc#TqzoWsc(WFj?R^!6??Jq(|DRmViez(i3wal$J%GvYV2ENbxfPd1YJbBusjxfV&@ zXssvcookre#eX3FiYTk%6rA+8?3=GG+`s991J$(}*s0B?n&UcF zGNJ!e7B1gWdXwx0-;Q#5a8fKjr~ZoIBTAK4*>4->+XIb>H;WelbTuBcilC3;?s}CG zaO&sHD2Dt^z&MsF>clkc{8DfVLI1648R7Z*x{Q6%Ue5{Xh~xZ4`7N?l9oUB7d(23!5bByYP@U|S9(<&@<4JU)HO)ys%!Yq8!VQ^ zH@5IirwnJz4#>#kS&{Xl-xkb1c>-*lP_4$N1ead6A>!^+von8ir7H7UYpk)VAJl2) zDSJ0-1_Z2$aE*>(M&}%4w*KI50wOjbUp>j11Apd3Vq=T#;7CH1#F?nN5c&Yf**lJB z2GTofr!=_Iu5#oAo)OZ*YeYySxinxkpR&o&ABHwIFDBE;(MOuB@C@|32r3F&Pl2K| zf_k|Sy42<5)*L9!6pk&84Z<3rOm8)Du}Tj~jVVdkdKIKFwxLBL|NCP|V~`I{?md>O zUP2nvp^z zIVz(mDjhiAi@@H**94<5_N$XnhmfE9z*C5H7*x8I0-M_up=0G43U&={AJ^qT`Uo8g&p8bGgBe@6^L zuWz4`3GPb#Z&4Xw8rv3CAy81Pa>JM@VOm#V@zm4vUtE*fYgA7vOGUiMc; zur@wnHq$8!i_Un1Q#ax&KYy(D;%4esyM-)0+n_=;H!)_GoW;VMk&2q46piAVX;+AV zPnIVrAZ7QoLmzv~fEG`FA>v%j-LS!RGR>9$#!DvqrcV6)^^CP>I+Xg-;_c`@_c@vR zj1@+Yq~S}Ez?CjgQr?1wo;JaGR~hXsOuCB$+dH6)e5+!|+fWGuLw`<9Lw=_0Jlxn! zdmCTy9y5}5_7p4q1p{PO0WkpMzxpC2nsJ~RpNGFONyARIZ6QjS;QXRe3K22YeSz|O z-xk+Md;lT8I^rpNhTjA;-bcpe_DZKES@*?joqMj2vfM&P*(tF@G&t1T_=}(7r3zw- zsTNC3L$OqNEzze%zJEk7)F3Vk+UVtrW_`gdg*mT$_u^}T!PjtKH+FwDi_?G18#UQ&(mAmAm+~38;1X*`-D73#Z@o!n_jK*LQ`G z!LR!FDW8IGK7D4ssk%)U#EjW@u4FGjY0Jf=u3f5Ts4hwD*MC4oz9AyY8Cwqrrs~1* z-Bok_u!j2oI~!^Rsrk~_U(w?1Y!Dc_yv(=OLEtTGN#P9;^)8&TDjNW(GnTB68!41b zpjzDq>p69o6-rbP8ZjfC)rc>47Ih!%n+Veo5s!SZu zZP3FkN(Qi6f%!X0O*k;mfShkqs%pUc#w_anTcoKCIf|H7nf+jDn zqXvm2tCaPY5M^g8KBZl46(s+{?&l5p8X_eWA9n;|Ue1ovx7yAfzZ5p%>X{Wn*XO0M znB0NRW!`oPF1?iPx*DVMrrMfQD6a@U$)91;AZ8%1QiGB|j?QAsQ6PY#AH)K;CGPI* zAOv>}e1HAWbIvT&8B+4zz1@N8Auj*4U`dt0bI|jQJYw!-6ili;Bh1eP3GGjGgAXjH z4g^&)krmhv?4pS%?rR@>MugeQROn-s`vwp>vCpO1?-UV(di~F!js#0-f z2vYF9=rg0Mslxra=abZV+bPjKhUh}-d}p>;VpU8G-2&W4aG$(?aQ=L2$-ui%Y1j1T z9ArG4c`~1qa5ZEitKtwd$qaRzqK9P6u+|KM-%4vUKh{bS*f4=4zJ`%s$up*`KP1Md zsDJE0OLzUAs#}nu;eYASC1`+RgXJciByVomQUr)U9kB4mfFb-<*Pj#i@<poR=*R1WLj1VZ#*<97`RC)IU zm2;AXi3CrXz^4ymts&poH_Y$(5?Y#gxf@k7w0YC_JW4J)mUyZb9MH3ik88aH(qn za?BvhuZ{I+*GWFUTyQA!>xn-QlegSKkUpcb-q#K|BObpKS|;w4yPOVBL6u z4VKtn6%GKMZNCsXs-mdO(h^;RrY^12>qU&2NsB@5XGQLp^xB`(PLE7TG2BzUCy3cP zo|@1=L}+dLVOX)jdIjsQVXFF@bfYm?_+IlpW#1t#V|OioA`1X+-vw`|A{-CgF9Puw z6WKbF7X;iZOSbiIrsQVY)1^$@tKeqA1>L?50-_;FtSryW>KBxdMk`xG#zZEKRS|ai z6X5dRYruzLv^p6Gx)HzQt5)dEE-OD~HsVQ2xxeqObydTFczpA9`L!z~%N`>CVD{g= z?Rp6Flhl6}0G?xAIQdxeZ)025a>y_~o#Ec6+9#Ka$$cGvWbo0|%Z<^N`~aW}fcuv& zQy`0&)HnTHsYFygw4#Xo7qAVh$aJ62hnbaK+CSbbq$C!+oUrz@!yt?rN*&9A5lQ*#TS4d4kX1Y&h+f}lcr5cY zxF)S%M7pzmFsXpIR@=97glmq0;#--T_`udEG3iu7_A&RNT$N0=TA$C&+)TGgG&r@A z9z9XNLOL|LB3@PpxzA#+W>Y=kzk6D*VCmkasH{DIGMa7w@mmN1JuDho#v~B;2fx71-dLcjQMN?*?f&BYE#)AN$Pm}x}%>&oEMWncS^LTtsFRxzRY1!rrq zBcBr_c?|L|zaJjC9RNm(hqED=hfF3N>{o=LA1k{DT;CiezJtjWxF^j`I0u<$hOt9@ zjWD`@0ErIDE5SnA_;zo#$k^^osXvsgBbSR@Zj?n%ce^?GTq| zSm7$hWrlfzQtsXBKIp?t^a>fcQ5sz~0HS5p>=Hg=(YI-zFL`7*2;XL}fHaV`BCTlR z#EMgzJ<5jm%MD?tl|o7q0ZsZB$cXf6Y!9w~i|#of--oD{+Gr}fzPt1m^Tz#nu>eJ3 ztn@dq{^ktv#(ki71}07xZqJnlv>o10eag84NvXSpRpE-SMZ?)2a*=SFhbN7>zQFOH za9E^GLB9uC>?=PjB0O-nx|&ai7;Kn+jvrM@h1q`00xVhWgI_K+s863bm`-OhfG4_t zdc5wIox%o^A$TruN(#G>WnPA6SuL+T+vgG?9WFUUpIq4`C1HtKTUoX=CP=X_yR6-$ z20CJwEOecIkUkT+wW9p=^%sD>3)V!wpW_=Vs1+AjeIm9S>%9PD_bMuuD_2gEZqm=y zE~bLDUAEe3J_tHy!0jVR&6MNLk4*D_93~X9LI~JEFq(jjeY=x>nVSti@Wn1DHekvx zT-dFF0bjDhceKkNaHY_Q3e$ZmyMqvR*Fs* zjdRC^v(eaaJdAbvLNgqEqv&>Rp7s*p6X-^yIQwVfK?IxnY1+p-iNjYMg3ghAf_f!k z1<5bC79T~ArDHF07Gc`hgDW0?RwDwdKxS?;J*xbiCnub$^0yULsv2^uRdN-*yuO@t z3^t#7JnwsE)v@Bgg9E%sl=O*2-Sal9Tg9JQur>3RqLpGESfejYF8s9a_tt`#fTTcB zO=k9Sy#dJkIkJl$EAB@|Y6-W(7<}AV!oax5pt?zgkTVh~)CyPTE_(CQ#=inSYNr5~YvpA>k zpFf|01pG@wwh=4uim&?HEiH}z#Ir8d)G>YxAtXdKml~=Ak>ZO4@pox%g*y2OTHGxG zx9I~y-)kBogH7}(UQ8Cm^CH!UzCZX%qPgnmkme|qBEEyC=-{sV$mi4aPuDv%GuG**Yl~>_ za6mtW^8KYMFZCEx`fnVW^_1<}{M|T<%ohHe7-!g_`&bs|Zl1h_V z58xoY@evIn-&)>(Xa07sU#O^+bRIr>J#&XG*fSB_AgH*_VwvEMGb1SZspdD)!=Vsm zzQ!_Z$*vmGu*hJ$>s@1pju?CYE2JOj)$A9U^=^k9bcuuAtk308CVl5(KNs##IeEbO z>^|ljRQolo^U?<(RLB~~-<41pQ{^|Tdyf8&ejOMvz1;mY05Xyv2`8ZdTBEVfUYVztNe}8-zMLkHmnn>6I^xSjo{Y|(&St> z({6CzP7ABEoxq{;nq>_vO)TSOYvz?RZ5Hx@K|5o)%#sXJ6rGlXryI&EdgpgtGaHcgO1(3;n9?@^RCB5g> zA>npU+bMX6M>!8S1s)ySgkD^Les@SXToAW?h#|20gT^hKY=jq5BDD}w7YCA+TuN;e z(N0&{mwC(ULPKG-2{gL3it@eQ`q~(^6Tq~i89k1A zws!k}+58QzaU|niZciFJt0S&ENh8*maQV^m$OE?z&ihC2hLm6Ro>q^FTYJdOKt*A) zukefdsK;g;)Yt0{e@SwXChW{lIQ!cL=jNX=Nh(Wt@(bsuXhgqZvzE$_$|h#@7DZpr z2moe;nobOza(TSV7;9MX%~0dgEsO4Zul5IjR!AlG@RcHyPu1IB+@7fJ9D3BSulrZu z;mfKa3o&MFm<^v+*uK$PM8Emz9XH`V`S+9Y@P|WiWK%%X9lbXzjq|7Ev%~A>2q#bk zrJZS+NyDQvG?6*jXbgHHpx_B)4DY<-S4LJ!WB+^eYcWU&5M`ps4yJEK_UpF9-4VKf zl>ztxiF@$10R}DQq9O170GTt4TQi^9_6;YeqTC94^mv4BP6c}Bhk(FrZWb(~A}Fg6 zTZ6xKvf2)iN3W+Rr=*n+qy$D=`k&Wg2YRsV)NVM}MiS{{0D@pb8{t1+334R9;hU|X z0Ajr|v`lx|NkKO{YWX|G-1NDl*7P!e!pZ?)LDT!&WK99^JPQHf)qHCWI27a4_V4{A4l+BVFI;9UUF}pH@N73icSpy zB-o3;TAz+T71N`<8+#<==pvk(ggt;Js_?ch(HGfM2Kd zyBPk+=10B2O~V*2<8lpQ4F@-&cCg5-h)F5|H zg{`WY5>@$0XaISnl>}h?Y(9V?@tj8jE(-6q>(e#-ZXSd(--X1L%sphp&Ns23+}P}a=euV7`|=9n(%9ik)!cB*4o37jBBd^W5Whf(&Nn;*wQJye zNgA9tEZfX7OmPaxol}$Q@vM=`<+qo<0s?sV?OesBt;5a@BJH~{nP0Uh%kc-{iR@4N zcVfeBg0l-io^$Sbaq)@YKhkg9pwhIV&%S;QR`bsrRb3w@Rc`b zSB7TyAd8eK`f;H=LeVd&G_=9wF?{rcQWq2LBYc(f0s!TADXX20OKSq62#!~Y{@lzE zD3N};_g6g5D$;qb*pDdJ$tRL>?^NZZO-uO^-28F(`|!_$TWtQz z2Z6YPD0%CDaVx>AZ0PcPoG9?&egss^9}e13Q!ONm>Kl|iM{Fn;Nb2x*k!{ce)if|n zSa2KZph>;$4FO2d78P!ma1$N6ZHv}%LI0sGh@xR&FrfNbrh;oQ#pe%1sVhT!U~ti zqTB|H);g7RR|mz8-zuDyjQ4onM8q-_qeMFwXbSe^XA`seZWw*}`Rr3w+oqzi9kT7>;38xFP{wv)bwJF8Kp~Bi1ULLKs@7$7ryNX zm&A1^kSaPlJE6e<4SYIgS+O4vE!zEK2XLl;;!_d_g827To8vmBMl#6go(n1Hy&`vT zW!ftLFsw%|*?f;Hg#GBTK{i4_d4u7Kug38gO4kk>{e9!Pu~LTA89BZU1KI4z*EAGL zj~@afFlN0_`TYVu4^BipJ=NIYlNILuy?(3lxCB3QXH%_r%BUbqtuONvPm}ku*yenH zzlOLPL3M00U=Qhv}nfRr=l0;whYxx3{N%$?LV}0CoK?<;Mba+OWQ7ifQ#$^*IwqsCU%c zLSwSw8sV5Q#231#u3s2B&HH==#Cb(#C_v=|bq#bFpx`v=pbL=PBoduST*Ky|tZ7p; zlk0q`T@|w^w26hlEQ|Q1Pe57YJ1JrgvFGX>4A9%-Tr^a`Y6Z--E!dSDJ~fel)&&`6 z*%c*ZzSRU06JB@na*Fr#KzzG?fGV#DC#dx`J_o-JO1C*L_h=tiT=h&p2ou)KdB-p` zA@lmwwHqv0}kxCTVHcdxlnD&?oMZLxYV} z=VS@AD>yEneSy=A7eOUaeN-`jqCogIu^5^3CZN$2@3=}XXnAM)S)&S`{HTvXK5YJr zzR{DcaApjPXQ#3elNc#wa7dXea1A2F6Uv;cwaiX$xc&VlMZ@+n6*^Zm1!5bw=ACO( zQ{qA&1vHCA8vbUM}l@ZDvRniWju% zgnh}Ccp4uZLc%y4GXU2}%@1=s)5apdR@~OFs={fZu)5Q{?B+0Hw~&O=W#hb5U92=Q z@AC9# zk%w&!Nv;&iyUmY5z@JGzTsthvW{j~F2lJ{qentB|)czLy{r7`^WoQpITDpAvar=Do zc3zX1SmMVMmxwYcN)NN5VA|Z;Sz~l_ zxuMcmfrQnQMp&liAc=ajP^)y~ktmlH2yQDcjx=>W47J-V&%JNmwLe)Th>xMj(yKM- zmWrrBZWOmeR)FPy2gfdQx$h>no9TUW#|bR``|3OtFD%K-*Vv($lcUYpi%(XVVa}My z1no+h7GL+{$bV0R5&yo|?}p?GRoEK1S;!~j4zPj;IMZ_F3+hfV2V^;NDK1L4rWJ_( z>E={bOUV0g8j@uHC@B_N-%^}ND!ucjj#%>i=D+nt$LGX<^>pgKj! z#Dr3vHN>6i?HCjKxE{b3?7g-XtKCcr7f_pCUe7Pm>jWe;UKVEu9E`9pHg)NCmodjt zv(XEYU};uLwPfjQP>80B>khzu=LEhsHFZJkZ6LP2t1a}RFQ@>*oeguO?{o?fm~Eag zA_FR#O*TA#g29i3ak{Dl)fxm9yne`ra#6*8;S?t|IIF!|Fp)IY?q69(yK`TeN%w%ulw)P#K_%J`JO7(@{eI?L@U3azYT@3WB;;SEZq7;UH zP(#>U5xdl_KfSnzYeI)~R(PFhf77q6ctP1%)>(aj9Cb?1@Nq%t-wyu9xW2FqtbLzN z<0?*nJ`5(nt?2Ggt`?BWuZ)Y%xRGPlTmAR-DJ@N-SVGPz=haH$2`>|yg7rWV*sqZ2 z<)KoOtZ~00oy)_p$1jmF%HQ(kU1S>=Mxh^+$f+dSZ|; z*No*c6#LCVN!>QyoMA@{>|x=3R^~xpezDm6H6>W6Ym$CXY>yD(y{L2S{Ntr^z(eF_ zzNDQsc9*QvvD2r%VICk?g&~u@#vPWszl+75!8Mza8_z&70Rl76+oB!{>$KBNsCN5* zu~=&AqJaY0Gk&;>2sKxHLE!p|D=7TkSLl$}QDeym5OnU;nNt^&NgIzi>>Uc9*gb3{ znit)E@Na5U;oj|1(i1X3ll^(s7ppMuk4x+b5psxeXdNr>pF)!~A}?+Vsop}cfJhz> z&gyHx_lIol>!f8k<>aA3`L#$ikF@@OZ~!VD(J<-ZLw?b$QQB`%BkyK#O|ku{BZi)7 zpy1lynd&jqCV85rGL7&3W&E6scy_z84pnBstycw04FoNY!tfAgD_p2`ZMNq$Q3}j} zb2mx&d(ud{h#Sy}3fn~NFIXxF60|J{D2@D%;sOwX$CId^|7>?^2$dJ0^Haxv33}p% z$^O2r*Vr6#ubS)LP&2d{(p}+kT?~443`?4JYN{$gThY@ZxIMi~p{7spS!&u2;N(Z< zzAE*Jui$($a=_=SfoP2=uygOew?4^^ZPH5%Q36T6;ddwc+Ijfpn$2)P)SaKnIxR2X zUSh^m%Cy$ZBGB}AN5>r^?tuS)(0#jK{f@)87)sWMbBLGVtM0%%wzc@xO z#3w5OU~oqsS#s#_`A@pZuaK7l(2iLDlt*0;@nNu?C?WiyCN z`0OLKeLbAY^7O}i!HI@-i>_=823@7%(0>n8nG{AE`bvbivuR(CRiUa4u9Kq75-KIQ z>ne&c?+eAa%>>haI)|%rQ`x5pq3+lGybLPL20{^BT5F7 z8L}yx%jT`vId27EiBcr--Y8Du){P53@#;K$UR85VcL2&Zs5K=X_j}q@c~ll6rvr$j z+3f9z6tJIYA9(!>VI^Mb9R&~uInu4df**h(RowG1Jq&OZ)y496cOL>#JH6ND7YxQN z3pJj+nbJi-lvg@`n__%`!??>DJ2E-RZ_8b44kK5tY_v2rzDXl*szirpFmmsu_o?RCSjpuUI<@;IO44mBF8b?C?Nr5|exnoD$7U44ipJZ*%d)j`h>|Sao@B;Gd^! zwC}c67U${5=LK9e40_5wYB!UwNLpsj(`JFFxv0TIQi-U4TpWI%5$;xW=d?w%gq2#( zEsFw_gtS#Ze+ck)n6*l1M*8DkvbSbxA)o{b)7pp0OK>M@sm^oMcR~34HkKEtbYSnZ zLL$KjrHdh_{j}mdLG$>Id?()9p(PZ-xFkjz8dJ{S4ip_Z&8dazv;Kf;Eld+f?Ym~I zFMEbv9%}7>@mgZ>(7_i8ias68zyp=dXmLPSNS{DFVos0)3{rQojh;aGtdKW8U{I|Y{B@gaizi3 zw&Ue6FbbPiF5TVd?8jLZbZ#3YwN_mvytD2H3ur_a`?fYDWDg z6%d+#fb`uwR3?aiWIBps(eE;J@`SIqn62Q4S2^n9U{Sy?><$Nd%12h8IPL?H0z*(W z45Eq+{D3cAQOCdfQZ&murCR4Z+{2zb$b3r>Y#Utq4%6ZM zR(D9R-w>!vZG3bO?H7Z?HziIdua&t#DPl=~TX{7#Kz&ODqi@DrrD7WhL;H(To>@%C zuxAwIm9zwo@(v{trfGLIyyID6MdaO ztWUb6*(~>O5JT2~xze2i1w5?<{^D-#^o(`Gqhc>dex+MJKF|DOlld*&Z%IVZijL8L zoSC)ZmxfC~GmI8%%jZeB2`B&;#B-wo0ytTtRz2jAa~m{TNL+C*D70#Q^)X58fZb0- z(A1PLPtx1aZwIbs9e%!5pX~fpB{>385H^jfm_iJPUf$O1pPi+A&))`KjlN&c%TAGa zo!P{iD0qbJi|lT5jiMV$7}jwEVC#&3-ufQYc5Y7oz75Ke$RSL+t7lJ=V4<2)Iybb#r~BH>T>w=p!qlBVALgoIj1E@I62wud&wPSV zhwN9Nx9mwP6~d>d`nqF|VNL2hWo-|`WZoM(2)r#f;WKx~!b?aXeBg9A(hT)Cq&9|RhMF?BoMpm<{{yU7eb(sRtj#U+t<-TZRsrx`= zB4%O4o>EVZbP>H0e=O{9g_VmPr6Lqzl56Ae^&beu!qbo$9!4^u#kYrjkm~CNj~D-h zCIS$3<-vl3xt`G{cpbZc<~*xeCc$UlBj}wM4&6#$Brd{No_?YvA+`L_o%{8~+T%Bt z62NNub3RVQZSx&6p*vB~3s)B^~Nau}kWpNI?W)9AZ@Wy-F`Md4Qghuo6Q z-%&x6AP(ib`LLGYrJ0@jjY1a~Bb~mzNsAD|UC4hXy4`map$uYF@J1Fih z<&tV%0*pr{){$9f@mm6T?He`>W^!Ey1W?WlI`S%C&&dGJ3MsWyzsx$tp5F7U+kQ$J zm4#q^KfPJ#!ns?2sofQR^SeY{r7aNBi3IUkEdI=^!LcXyOqaQ0Hit{Dv5-ha2=-TD z5;OZU=T%I;!e#s?^D#(eK41S=-7$pBDvxw)Pte;)~ZWP;ap7z!nWS`hTphtU*Du4O6*vcgDq(inKfq1H9dETPj zZrQfD2PKT)2b~_5{(eH*a8(5JP$ns&6u*X49C{-6=?wzX(U^I~|Jt%lqwTmANIecJ z88ZEOzOH?Lwo;Sx`0wsp@>tY*DSs^vWbsbNUDRb}(-cM~lfm$VX*cSC#AOd)DP7jm zdLGsJ65Qm|uf%)i2TL@fW;T9%i+vdd@HRF<=n2OtD}m4ZM;7wfnMEb2u^t_3KCxvc z6_o+2!^+i)bSa5f;3eJ3RL=B!?`_9FOhCT$>@q*T;Qjwpi z!xF(Sy(|`-pIth*;wDJXmQITVLZm{t2$Ph`53eQvec0>03I2vIZ!~ z+_gY|v~925icndpS#3u%T{r~M6)0?iXHMAre#&(v+Jdz4z=F790i!1LMLTxiHDZ6E zrf=G9sS>zB=2`yrH>-Cbp{f}-?v{ix@UKZ4dXZ(mBhEk#!WPwZ`Q^-d=H9fAlb~^Y zRJ+(luSGU6wTvq!TWFhBQz1WgoI1NYg9Jf;pK4n$3wV4Az74WSLz<5Mw%;>A>KOX! zdd1n-=ZS{qmy@5mSUtDOL7B&Z&x#1`asM)y3jfaChH(P3pBnx_aTo*Ct1*UW?m!-I zcd-*(Z2!3!7a@M~cQ|_7k#4<(}mB#dTk)@29JGJANopbZ(HJxOiU~S(E~Q z*F!uhNNe%n^~i*d62K1@I>3OYSw96MxWWVh94N*6;{l+UBRG84FDs9`4Z!5b6Mo4- zX!jP6^-PSa5zf6Vm+W^2h@35R3iz10_rW1sb_4Bx@TFXiXjP*rx^D z%?3y5j=3tkd_#G<;I_PsU0e8-1WdB={!ohWnlw#+K=e1<^!Z34YIqsC1i9CL$sOx4 zDdVrX*;zrmOhTo$lr?3xZR>D2m@q@R^ur)@5kpS=?T9%8#N zhj3@dy`QOJ>eWU%em{@>OuH?t;85_Ugf*Wc+@>IBj5SR^UJL&HInO$Lyx1ZJm&Odq z+4B?-7LtUl%+~_}?Qc&dJ9=DykoH=Vr-0$9j=$r_Z9Gws17@U zsH9e}ml#sFYdxCGF8%rSM|3mXn6$SsYY$Xz)3nH6@hv!SlO~0G3+WpObB7Vd7vE$4 zgMY@zF^__(B98+sS>^2#8D~_}Qw^E}8&ukcVZL)u%P#rO6q~}*+r5x~Ju(}Q!mJ-Yr9+bcj7`ex!#e{+hUh{cMp23nODw)-3~4LP@n<}TfPS`*5asegM{oc>Mi57m8>Cfedhg4=XbQJTyCwVHC0BVo;?8t>nF|7l z|Bht%aw3^f(yqz#bB5J_{XlIcF@0qGi$#o$_5aUBip`SJSIA9>l)-hjLN}L)&|jW!Ir(SAnXSsrsjNb zs*JwTTPe064s?dSRol)TUp&|z|a=puF5&fTwmrZmu^$~tQ>irP3QM)@XXf3|8q zu<=Xa)HnT*781?p1CXQbhtOQc6eRjvZTS=`;~Va$AY|7^Y19SkvbY*9;5y5am5)hKB-lCr*p&sQ51-8_CJ$f04+ z)RE`fy?nK`GRJ)b2iE?}BAA8yH=eDhX#^+2q`NzWGtUZVeJijcv zbLr_oa4)7oj(1=!uHifZ8wJ8KhcmBO6CHT)DLQQA!>xNin>jvrpykboa>=E5%V96Q z#)}}?#K_T4B>JhY#<*O$Y_kst*C>Rh6ivshGE$B!x?yb^osOau?wF#m%+gV12%EgY zO2~OtNJemfE|AcMsDtVdyfekQ?E~nknkle25-!qQv)Q>^{o9GjRBFGu0D!r4+E{D= z(bgubtibP&K4%kkcDje3UjW_U*ax{i%P>{-=pGu8`a9VL;)YSQKN&JH3-8ArHs3ai z>)%{)UvalQFf`*7r*tW{_Z@b_fXSO%0 zhW;=?rzY3nCv<&Ori)5BB#?8vA8?D;wv!vfp`!@n+-b;2|J_cwGI`J896S~=I6b1+ z=F@Klyz$$=)4gmm@k&5Q=tnJP3Itx>d=qn$TNLBh<$%*GKT^)qrFG z{fF}q!BOjP%1UD%oS7aKL29OuxQ3%OuzAUU)a;S_uVGO5qsPMZnsHh;j39a+6;ZL* z9%*g=S)6(Aimv0{xAQIlP3~XqnCZYWwMYCyuwnH^6#aF#rx(>T2Vv1)gcq(%=D!pF z8l(LiR~o40LEK}Q~P*e8Di#QsU`cfNWuq*#p~nZP1kxQ2|EOT0mlGM zK(fE&h;~*O;abWt;DI9!bpEs?v*?PS-k`_a)Kn{lJ*uqH1CLoO4H#Ma}+n@zPk+J{B@b@)n*+Uo~@d%ecE>E|ZRRTW3A5*nAu zFX(c$v!gOeN2rXR`z{>*NHi`BVaarLe{g3w;8izA`Hemq#T?8>>;T60RIf(UuD8Pa zLrL%r6#|`1yCeuj(|oxsS>2Lp~! zo#b&-+LpO4jd6D82u3u)TfK792)aFK*;{8cL1RxTd5yg4$pfWN6Knh^zM|$LSj)_p@==fWDm}51AL57b0vcih;(-n}r=`OF{SKCw;I&4DFGan($dfg*?Z4UQ%xcTNLjORcidgNM zt{4AlAl=HQP*R>4Ye7Vmx##{W=dfYU2`1456SMD(F=OK`9JxR6b2w!j5Y=|ZZh4+( zJ)gdf6Zv;#n8vTd0DOPN#ZD2j_vD#z{M0%bH7{Rw0anBv(FKrPX}duI;Wp4sEMYC5 zPm%xn&+ot+6d_q(@HJE88j+MX6UE8KZ&oyHh0b%b0VxZ_n<+dbQuOa6jnR_X-;EB> zQ|nuUX4@I+F;3Zd@j{@ANMq*n5L*T`;B}(Lom4|ysx6HTOXq*^&|k9eCX^)Vu}0HF zN?K=P?bIu)5H%9{&LX8Q~RdDZ#JI5!W|C$Y%)cO%iyF}FA6y` zh`Pq01PBYdg_vj^hgyq)NhW-1)7%SGviYSY!11h0$BH8KLfKL^v+byTrvM;xlG5Nt zd<|5DNr``Vg`kIb3QpPzVZwdvi9FaCPn&XV! z6m6(H!g_(}XU!b)bA2W|wBdn^rf3o)2j(Ie9Y$<;h(<0_AQUP-i2RvX8+Bm$KA|bd+JBImeW=>~r+8uCR)4>El*7xm?~km;Kf`cTvN zWFB^UL-Aom=gCz7lwV3HE3bk&TcBlH_`|Wa($Z|dB1ALOJK!znm0H?|Bt_qEA@5{jGI(5+ zjiG-=i1TC%FLNLOP8I016+_8ckq9RMoaeh<{XVvpm(*0?1TFLM3)WexuX(AXh)vi> zkrf&zm=j+n2Vmb%sb@9@n*x~6#tt9)dL<7rKuuspIBGoRyt0o>edwdKf@gce)aRaJ z{M4;FjN(kNjOKLKw_8p498taFy|@U z7zxQEeN#A>)5c=41M>;IREe@8YZw^2ZD1iJx^#+C-?Yr24{~Ut?XK0Ie0Wi8YI28F zB85Kk#og52tb%gM*gZST2$~{6IYSeyIX%^v_0i709UwcqUDeU&a4gM)?&6eJerN z5_;#pX~`z!GH~frI|x$IGpa-_qTNBF;KCR4<4IAAcwczwt|2Qv*MQ zeaRcleELM3EPW-H=MX_g{oEeKdhbfe?6JeiJW(VNQS|T;bAdjmsRwek zt2;Lo`eI2FPluEe4S#*Fd#yfI4D2bYfxAX4W_h`xnzx7RsL9PGm5d}8G{E&XF@!k!sNiPGL8qTkP6_K`X(idKipF7VRGul zJi!=#3O+oekd$LKS&_p)l8<0<)+yn~3Q8CtYXdcjKCKmOZUn4s`oIS6F&MB@(p>6s z_NlXwXUuF^1e9AK%x{1>=XK=N?IzE-FJ&e412I~!(tmxIv>SZsHwg5HB_yMC0VNB$ z8}_CTO~f`i9OE@CWP9-Yhb)=H4q05z?KOP1(FFCFXUgnEkHM6xSev4BsdEU8*iGLh znl7y3>Z;z@_XeryNqCptl8gKAuxuKK`PX!v-UX#1o-20e)(MjA?gCS%;GxPLRF zSDIICZi2>K%AVAM92E5~EwgN|<>PZ-U_N9ap^loQ|yqUU44z3N5L4m93<;_eiGsE?0D>7=iL( zVN2WwYUvTkplxa6^O?C8R6YN0L%eKgwW6W59xLzakka`Xhzyclhqur5dCMX@9)F>% z+uylQe}H3Vw&S1EM^X8;L^afX^qhjiki~DDK9}1MppNhB z)u*cfWF+^XztjAwr_S!gAOrs0Jcs@~c*=|?`aL<+oMF?r${m8geVOZky?>#GMx)m) zthd$T;xH+alTu2@T0*yCrWEl(|g|$AYKKi!UOAX4wG-8a_q5M6f#Q)xTSrM6Z`orqreNAX+ z0s}Oftwy>eT5-)E<;qK$cv`aJ1sHT?yi;k$Z43m|oH6t_iRuxQX@6zIV}pG5?D=AI zGcWv~PF8I>JD55T%Lfg>Z-VUPG~nx=#)!b!$?YZ&a_Fl2baPo}(HCgqBK4l}B&DXy zATKUFtMVdgKH|J^xcXIBpUs=YIUiDO>T}RQR z&>IV+fK5HAE?NfTC+!HQlB(suGl-(D^mMoW`lqGG7WYdk;pT;R5^{fIot?_zWzss&Ue-I4UC%c zENB3LmWQ)HiQtUjhS0d+y@o2;t+zrb_`?(uUvSuqC4c1D%%7Gx%uTu6wjT@5wSMkk zIG8^^C~@RA2~r0shm=3qE!Wj}cdI05Ue;Mn-vSYl-xRzv+(&{c0P^=z2DHjWwaKgW z36pw@x)r$A>IU>|a!IksP6AHCP6k{!wJ|lfIzVERgm*uVO!p{cx(( z#;?by#DAVV?gG++dXatSDW4BilfT{!fKhbd^Hc{wqz)h#LE&t73^?A+R2B+RH)5dt z{Iu3$^HVdTGgtBk0^(guF{)|biTM1=4*{Ytl#KTX7kv_giW(ka6z(cnu~%P48E>=t zs6F8^&PHfL0q3{kJMcE>znpR(<*gz1;FMIaV1L^@U6!T$Iyusorm*EJcB!42ky+J+ zzW1oGs^H(vu&AW>HRasCmq+wN%@^h2iG*IQtk{XM2S9+r z!hihEyr=+jgtks1m1k_5M(!MVHkpT@^rJmVcA8$@_8vOL{7RUg{(Ul z-$AG?6ufX`>Iv{}hxB&^D3ek=H7uL%y9JJstV^@Sb&Dqlp5S1G&T)bT70(&I{xBqO z2Y^63ps9g)7&q_sSP(d?QyDliBWUiVGk?Fy2TU+Yx+OSD@ZA6<^J4?y2aTk~%hYs) zpDcmxxYjiHx84ba=)Ve|PGEszOv-50I%b~JH++t^XN)cO%ci?io*r`g1CJ1*Pur9 zWdpm6)#H9h2#Q{^yTL8#XAXyAr+=Sz=@5QPjzYZV;iM%I8mDP_o#hT5zB(#=kOmXK+1Zrc z_@#@aeRnT{o#la4)4U_dH*5j0V1e)CL{3#OtJ**WdVUFQO*#-F#!L|>@_%E+uEp@f z6F*b^;#K3<^KT{<{8a+Yzzrz1#r<1U6jPc5Sh%1eJ{FkZSa<4s5|qe@M_~$jvt{O3 zU^5I)(K0v=Hy^|eWGroenoVqWg8oMKNG_*GQT0Kvu4k}xQfsRM#RZeu{pe951XQ7{ z2rPx6m56>Upo~Iq5wn33Nq-gog=+g_>RD6s_2n=k3kvbVWbuzc#wY<@Z%384yKVc*P`+Y^hL}r@W?6#*bQON3%~W$ z;XRgF?&HY1Tr2rV0y}W`>5ZwXwwxh%vT=ou^=U_~@%4b;(I0I8cYg#_6#fb~+;egT z16(K5pB+%@9Ts<9wA;L7tRTxt(wGpcDShAJJ-A@ylq0(4AzWGhl3Gk#*|UGH8g~U< zq0MftDkZnAl;HYq*`!JCx2U^rtP?hH;))1@zZ|<4$-sPtATq=&(&zwbQ-?~`pF{U5bkk(+#UuX^3K%w z_D$h)s(EKA^Yj%UxbrN1-p7gM9HEyY@wx_QoVgzuB;6`kE`P+7>--MM)b(B$lulCo z_{XJ!LGaLw{FVmNv)UnpAPRWNgiBN9996bw<$yczBcSf@DA}5?S!TI^1wWs`_p5%k zgGz0t&e`Y3$l#}$g&71IL#)tU)K2{t;P~z)1^?)WPCYMW? zno8<*$&wQO9Dg>==}}WT{F8*|!Jyiwey8$X+ID%r#_mY^@4}b7>NN?uE)LeQ{p}cB zP~rZknSPz>a2Ev^fcpEHd==3qdPs-aeXgVV_UMyiJHckcl~TZ7I(15;em%boJVNmy z>+Ag%!@Aemi~L*J?se);Y@p)Hq-#D{@$v1r)wuzX?|+_m=On=M_|YaOl3CmK%4f+Q zQ)m8EJ$Y&X2^tg2KXV}yw}FYeA(z^8h9D0x4aFg!zMF4RVILR+i}TiPa#4xu_u*z9 zP-U_AL{~lhG=SNtnc{sftJPY{^NF>#DygXA&vN}`3IDz|b-;BD0Iau;(ogP!*&wh5 zeJQc0YJb=9FQtZcP4iMx|5k$Ik0JX#)$|rx9+v+eKgtg(K?s}K7ntMlVUb$wisfs4 z0nuZWMSaY-qlQ(mm{z!T!^RD8{gDhG2XO1DYB)6B3Hg0^&YFJ)1`XRK%^T*`ckr63 zzc2TP4qk}jz&u;)YPl*bSeWa>ALywU<~myX$bUm^f_%Z;gt>Ha zV!r1bYp$12tC6q+srj;>vzkftcg?WmcPTSH!`Q5Eh8%oarm-4Ws96LCqoz%%ha&Hn z!@XYn+@JN^Z$t2lt&VBW%$iD_6Ak&hag6xrWC8Zd!+{Z$WOw(OTSM5tExS78g>Gr- z6MwHqots%Y>(lMj!*T>#g}XDm{mvzJ)FK7OrSrO|vw)d9)kA_93@~6S_m?GPDmEN7Rgb+FweLqt)BNPgrdyuu0|WW1uOg!fxjht zWld7xRt_eVDVUA4#v<0F`2x#vblMI?sDIGCMweGv1d6XBUG%;VZ`CK-$3qJ-=EN}z z|KSDwwF)Ygiw|mU9`r5^qHakFq>E_ON6HprZ38?sx}vV%az4d(;IjDTpp1_AKoAz7 z98io&G`_DL2O5B?4-XYU6s=x6DlS!8Tmkg7GFwo&E>S%eNS|HaT{g%@peV2|F3W z(D$G(*Puwcdd4?id<@iq!5D+T+&{ zVXx}jk#Mt0py)c_N)d|e^|Da=3zlvU6XTs}!jMe)co$}rTm#Eu(s>PS0EHy% z)|^G(Fh{}s7pfRdN+sI@K!46*>A%yUa=jcx-swWU!~CG1MIH?>u25r_#Y-xfyughX z-!v3Wzb0)} z6nzp$F|4Jkk!vhp3&oja1hvBghcA9&Y@PLSm2IX@YM1{;EHZ!Z>3^n%bFCTSrn5>) z*(Nnq-(DT-``dMK885eAJVIH7%BC{?(<7`8!#3rq%Y$kL@TCaDz*N|q2y`{zvtybW zOv9>!BFcq|C10EAEKEB#$8d(ZI%DJu3))DQyHz50lz+(Wx6GjJmgO=UFpD1jw zMC_2o-0x=^u97lkU@w&6qaa%wn$~*6ep6W&WU+Z!M;E=B=JCx){OyFQ&zsE~Kh_eC zGGyEqBfHOa&VQ!@ec18tGHak#js)~IE56cABH(w9TXcVN3Br=^!lDG_#hiBCKJ~bWQC|!3Lv)w$DhBGl)bYm@p1$K_F5xkP4N8zs$b663}rMX z^-Ww}M7~ks4Xdh9rDC&vZ5Mgv?Ri+UjalpiN3CVHVq&_eZw{__x?MlH%|g1VfRCZS zHX0=`&3~I&wWQuLOfPkHz=QX1QVIoi_<3Q2*ytYW+-6mdQ`ZM~dno~kH#kDb)h0?+s@{`(pr z^<~qVc*j6N`?B@f61D?CmqEHo)-^8&xnFf)G=C#BFb|A%DQ(b7|JA?zXisYfYy7FC z92(%Y**-J#JASXNz%<}M*U$UxD4AjIZ$c!=7VLIjUmF+q1aDO4f?vZvaoE*0PVc z5%LN@#&y1HaEVk>V;>WU&L_D!T!V3Alo01DKT%V3tebpE>v;cPsem4oXNkjlXmW^4 z`|Bs)Yc9#}(}-^WL0{xBt!(qA9hr1>S}tMX=YoKLD^piHEj`maC_h_T#UIRHfq%L4 z8JKgiXv!vy-5bG1NAX6f@H=`xt9 z!z41a&~#DnR#hx>e!IOUf*Xnkb+3JItOd&$5^Ve+j#_8G{Gb$2NReJbo%@|hkuM9^ljT_ zgW8g7zlyTb(jVxEVP&2a^0Uz0b)$?Pe09ER`oi@KyoU|^gP=iYV$`kr*7r;Ai3SmY z{UPh8DnvAW+41G4(zL+FJ;Iy^#H{HGH1rZj%-O9vHH#$MS}o30R33s~KETIBJbcgP z_zjW;i_{+e_SpC%l)$Ne`hOf$%*rhyEp(hkM8!8-K}U{+U8}#guCmk`u1mHYON^%( zC+ZMUL3@e}<>=u?94{s?bzfUlXZco6*o~7siiXa>Z?e+?;SeCQ7z*yaK;9VQ0RAK! z3){>nt+v-c+Eji?EqbUSudtDTk%J+1PMA?5Quk=wfKE%yutq=4>3^tt2q8!gmW}@w z!MM}&xxP{`A^Rki~2RVLQYx;x(le8NZUk8EXmk4dYFE?qb zx{T{3n%6f4>G3y?eSi6qq#4;iL|06hB(nEsCk;D0wfOE~Kb%veV(C|oLivkKzb1$Q z6sz;QaR)CQijH^b!^f~9UOGMp{Ds}lrAb_!p@i>9o?SwA(XZdU^oJlAP9nPate^a9 z27R_7pj&vov}}4+5fA7=S?nA??CWdP=^|FtsJiAZxt|hv_kRpj+Tc&0q*%HP#KqU=al~K z#-I)lqR&KO(+6rAFy6r-b=;`bGU<}dnxygzm`L9efFEvr43^xS;NG&iOEAH?kkV| zUDjHle1KmBH`ZHos>Bz}XV*Jb>Y1OmmQCj7Ko3mI;;w`4khV8XwZeqO<=1>!j^{$-cnWU5b#AvTRImIxMSr?$?1PeH=5OGteRnL~*jv2u zJ!JC8YIe52UBa(~bkHS?t=>+^Mb9f$N5qhMrEd&spz|9YQb=G^y zZ_ypZVjp z&4<~koun7`m%e~%4-ATh0KSSI*YAk$-wA>WL4PLdpbxXk1}5B%ydT9#!Udv5==$ad zw=MM~atiwBfhJOd$_b9B0!;FIj=Q!m$*+4lJ7u$b_5E4KTi{u%F%9YUF+Jix^1T4D z&w>#rqvl#!_igjaFG|TYNzrtWe&5~zb%YdO*5-KRunrs+jl2K7t>b;9Pbuc8AneeI zX@5Q@a)yVgjKIEonp2tIZz18(g?TfyPQPd2ZtCx_=2v))ZN06d!753h+>yi8JON%( zcla7fZh=OQxjF(D*8C;bC`1afYQ>)_@=rUF%@rp1UWozJ@pB+reuAohV;~ErZ6-J< zlkg-5O8Bt2^83#jFWJ~O2FX*35WQ1hr&)aL=f9(Bfv+KB$E{xsJ@2^;{H|)3_s=Y~o z1IXKbI!sX#HBs|Ohr_{1GbxE8H97p>jZ8qRs!q?{b;CY4Zk;&0YV9S61dvGN@PFi! zaqT$X)>;qNt8ML#cX~aNnRc%316RBC&ij0@nYEumez3-)Tfj!|<@_}7j)G>&s`X*I zJuIGfHMB@Y`n~$xd0qys$+-L8R_{hyep1t+gV!O6B!P3#K@nEXV(l9$* zD}5X_N1Ze~ual};6_tGiVe zQ)BL%=dz_(_0oE5rsI9pzYbrUTd_O3^U$d)$f)uJ6|S;_A=g4BMfWiB{a9M zXxrEYhg-Cn+2L;T)Z(Z)OI^FaGM&vleY>++qn@RaN2y;8pTTkRHm+oJ*?*lwwWU3u z)N5+y-RdT@_wBi=2U)Riz18<}XT`l_MD0$JH|*uS@vw?=a*ed0J8Km0v^>T4o@0cI zd8N+k*0IXL65}#{5R~z=%$#WE(!U`H(wT zx15{9yY66Vs||Bd>vh*n-|Vhvlva%*UbTF0>xYeAHh)!a;!NmyOsSTH*W`G;N9?#r zU!KklRW*Ok=Ek`;u0I}I(#WQ_=5SsgF2=gId^u({NeA?j)<(0yK7Suh75Bf_uk@I7 zv(x1jDwFDMmS&B`Wc{?d&!w;BPTT5}mRYCU@wsDX&zq%dJ@ffE1%+OV?cR1=8@q>7 zTYpjQ5k-f(!dIKG(7L%S58KP@Y2oAKjDNC7Z4+AkB5U8Q&UhcJb!M!UV}C+jLPjUA;Wsk1*1J6X z6}v8Wlj*KqD$V`*J=Nm;*?gPl{;S@%2i+=jM(e{ScSWHc_5<CS{-< zUP&=hFT44q`3iUMdpCaQx5spLyqoTue`|DfoIE1>et+5AcJ7aUG0xuh!{H)yomPIk z?i@R}{xfsmUT-istotl^B*kJoZtr(dT6oNz~OR~~RPbKbtU zZ_lA|n$PC@$7yi$f&pFR&U3L{hTCuv8dIG%m61BUjt>Wa)KMOjQ#j8Cqo!r%&Yo%q z)q5?pgnu+{uUlePWAn0HE=O6bURmB+%?ERf+xcf!w3R3{zV)ZQ=4Hk13lqc2vAv^99QI_Ak+`&n{LI{fCVt&FOckEX+V zD<;S1Eu0o9v6$v1%fq^M?m6WxiQkX+^`zzdwSRHBr_I&sl+eq*?@r&3&VDoJ?nbRs zJA~5~Iki^z{#|ub(>k2)hB>pSRz5GaC>|d5*U?kxu77mwlFY-Yy}Q|Ucc(0rN6V(I zMR156Uq&8~L!Pm61#{jAJ@Z1CmwK4b7c7J<5Y-yLt<>ek4Y!Iq`*tQ@0^kVWmShF`1 z%UC?u$4Nm-Q%MU=+irJu?_Ap2J0_YoS!mkKe!uq(g;g7Me$1ZZ#VY8X=HB(Rq*1So zx?{4vq`7&R4VJHkGA`}gzBW{>$1!s@?Lhb5=lT}tZdQBCt+b#s0+4v=>|)M@<8$a*_f z&*K9fo_AAXHl5An;5MF{t$S6RWPfv>D~&}vh`r5mZM<*Zx#2J8^U*1vg_k^a_ZD$X z`)PzPHsyCy-ztaw_bLpQ)hcpMtzaKrSEKDF%Twy~JEP&QyADsgG}*+ft?AoVJgiOg zXSSI=7T4%FxhykoJ1-a4ho846C%-l3w(L3CCsQ&cba`v)wQYBk(dl|L;eW<)W173G z%eEgTXDzsg8nFKk1XNXzCN~tP(Pq_A;*lTadDI@WnXmp<46@#waWq)_JJ1nSZv4xm)!f_w@Io zao%pu+t>Vj7|<}WriZ?HpIo`$JIxOzrGxF7Jh4ain8gGT{Z*5h}_DZ zt?h;%0~%8c9q;&lvVZQH z&DVjs`K7gUE|cRxPX_Z_XZt=G=T>#`Ufz4MAMCb@w+gqj>*00FtjF$1bcL?ktng;% zHZgA7O2NiZQQSu(Uf1r&o)t) z#br`ktfR&vADqmw^`7|KOSWnU<3n7l^89(9lTmh8Q&oS28>OG8v#J*7n`l4Lo^-an z&0f8#xoSMZMt}8a1|I9%npR7itNb!MTRp4S%+<)>ZKvyMn_s#uYHn$vnZfK;D#e&~ z7jw<%&g*`{uET+1>*su0C8u8FwC@Zbn#S!Mw{L7#Zamm-9s6{y+D*IJ8nlcVAA6?J z<+{`=duOZLwf8J9BX!kzH>xt;Z=!UR`R1lr>}bTIWPcS+XKrWqH1C77J>CVmcjKOR ztG`T`@nm6=MT@YwxMWe41D}k&ys8)bu|~A^l_lv&8~d-%$%t&&B!%uPq@x$11i(r_BOdE?-6`^(9e_hl3+`Rmfzv7|NL)~|}*In{gQ zW?YS8pMR@aw{cj$M~6p;sN>;#W>2@3Ld<2<(5hf`(Tx>Ruan2Lze{KBhu>-}{c9&2 zq}Rv#Ic+bRGj4yI`n=p;ox!$hw5RLA$uNyo^SK^$hHO4NH#7UPJqE32H;C^=E9ftp zRTbIYYTjz~E^VVZ+8<1_H#lzEi_P{uE%%MN`hOl?S2kT;=S{Cjt7ZG39?NCTK2+yd zBR%E2Rbe=b&e43mGJggbgvPKteS5%FBW~9 z-Rs7=kyKs00`5HTlyz@I%Z(b;jMjn6b;Sm(8r5d(F=~7JWxJy;Z;Y&q-DIpgx8qq~ z>VJ`M&t6yEy6M%!^0Ij{A4l63ZQpz8W!6f4>O_N95c8j$6{In0%4t4AKR&CX8 z4{vZ~fpOP*^WyYsw^+8H1A3Kj<>JXGoWkjXd18SW~V3X_3T#da&)42(rZSuO#?O9LF_BXP8t{%_RE4${MdU&L_!^7Tglk@6I;(1mKTD5Gf z3?|7s?A-F_qqSe!TeC6O8)jurOZ|N7W^9m$*~m2W^;5s=yJ%-8yP3wta(|Yj?R-?X zX5HFys_06tTEgjb@ZKk){+1mKlFuA5vb==%5PRJCEB|~nHU(M7{ z$7xZVqv8GT8Ros6_OI3St(`9K{*q_`w{6Dl+4WwA{cXN}nEm%A_wBjASvBeYSdO-} ztv_u(UG+9!KAxRHsk@u@hJWj8ZR)gYq;E~tW7SkI(d=QY8-u)v9%}d8ofPLuveBlr z%FlC8>rC|J-A=P90Xt&81r%T*P&)MiOFD%y9rk!br6#iNprCtA4rHlPyrHxMd zdTI{b+Irf5H4esQIt%0eXv2D~HF4}ta}rJ4{n^C}on+EBk8FHc&y&f>?u@GF5O_f` zPg>VYcx@%4jvtWan}2)Y-0K}jR#L|0((a$HbABlo)-p7YNj_>n?v3+2+uP~r`Usqp zcX?D+``nnt!^g3^Pabo(Q(9zMyE+r?u&WOJ+o(tS?Amv|w06JV&W9&1Ew_t* zj+UyuZ0g+J%lk^C91hR+bn_TJ{Hb@n7OCc&-TI*On#HM6O@Eg2lM$WslV6^0cGoiF zcP)IUl~$VJ+HZ{418cTBb{ppORa-kh{P*OldToDaUW;V^EUid+o%Y&l#C)Z(v6J)W zOtaU@^Y@L(Gz+W#Bd@pjWqlr;R|A^(^@*m$$?7;5(C8VcU2{;Zw0&OWLDs$YqP3$s zflXSIcz<=m!P}gSY1ug%^;0n2F9yzTV!gA7R=sF=*?*H_IjZeTXR}`J^u}X1>fM)% z*?bVL#?RWVcBSXn?J%tcy}k1+M!VPApU`*zp~s6|JK5&VB3c2`Oy?%Eb?gVEoQ#y? zbNA50yp`LhL!{chmqEJLYGAIOhqI9A{ z+4757y|`S?&9Zu&vvkpF8BK05UVCmnU`*K$Cb2!4C)Fuqxw#LWXF6?ld-eUvc=RHA zm>t51gnMhz>&Am~-MLnMsn6)BbqVICW%#;dRL%PFJtRs$RHjFo(AH^o@A)fzoTs`1M}FFDIwuxfW4E)| zt^1)<-4D)bK zJ3D{8h^O_<`pzEfrn>6yZNhH$-n`$JZ$NaqyR8{}YH|v6nE3*#9Z2`1y$6kj-%32+chmRmVamm=7ce_*2H1$)j7Zm6AyL87& zc6>bETdwch!RBI(Y5y>K+3R6(*ln`+HQPl4MGJNdXSCWqtd+G{S%demn=doIX!UrP zGz}JA-X~?_9!kTp{YFsBTh1hJ_J2v(Xa`349<$t;#OdhB|2-Rw7S#8`IyJlgvnXp1 zwH^}3Uv=n-4AxnbOgi-Fk!aGeyqvqLE^*FDIx*H<8_})R3JwNStY9#GH8=gKk`I(w zZ{D=qho})gW7>O0#}-+1m*!#ZWtUq2Z4IW@wRoOyms@+2*5+|X z_NQ>z?9W&gJum9vIQ6`=acMLj=lf&y>d%5%oZOaKw%G26R!9C@E_-e=j?`8 zqdKh{`+G2Pdg^0szc)!_X1Ygu>D8xNn)UYWr17wytj$j8%yE|fVXeAer*SgdzEwOA zhga*^A9dB8dbpp9XYX)cgn!M-+GXQwRrP~`_UhXE$!U`{UvIBx2i?-m@@02mjml&) z&o&vqpqrcJE5EGMc@_CVzg*6G%Xa_XbRYJtVa~ZJ&+Vc+^NM!&Ff+Vl+K-Y)-Ap$@ z&^oQl%iv+m2m2)O-KjktuyZhag{76M-O;8UjjPEfEhe>n-LB|~MSr1rxm>RA$2)DO zN%t1jw$AB%){eDtG}ss?zxC2deO9xZ>1gP5W=R;SgL)dIqesjy$g1aS`go)8n{mZNSIILUOQE%#nvEL~>jonX-EPGPCz3%FJjq-ky_D&~fPKs6L$b^Wl%3&hc=jPR~sb zJIi@^4yz5-{jse*+T*%!yTQx74Ao7iet#OCtGt5Si|o42*niO%igk7x)LuR6|XD^?s<0{HO}d5q~2CaI(s*Ks;-~T_Utvb&2D3M_A`EeJoIM2@z&?gdD>~Z zgZh5^;G$~-)8;dGolBNAjTQIQmWw9QW==`9rp;Z9!?2mX@9w^+vW#tZ`#fD_nzC}N ze5$OdqCGc#Re#ZJYcuWCu7kA~Zg#!=Jr4`DcBgf7v`al=$8=BxO1V{(##z}8olPs~ zjyLD#uv%P|V=d0M-4oq5ANgWG8+5&pv>j(Wx;d{_S9hGpx@;a^>wC&NgUV8zhO@pc z!pC{CR!61v>L%7Z+;AO6osH=?&LexWek5sr8I5X_@P9Sw&i7d2-?k{MH?>_3