From c0d4b523c24e88b8c70cd3b121a46b7b3c841c17 Mon Sep 17 00:00:00 2001
From: zhongtao <zhongtao17@huawei.com>
Date: Tue, 13 Aug 2024 20:33:28 +0800
Subject: [PATCH 120/149] [nri] add convert and utils impl for nri

Signed-off-by: zhongtao <zhongtao17@huawei.com>
---
 src/daemon/common/nri/nri_convert.cc | 539 ++++++++++++++++++++++++
 src/daemon/common/nri/nri_convert.h  |   9 +-
 src/daemon/common/nri/nri_spec.c     | 602 +++++++++++++++++++++++++++
 src/daemon/common/nri/nri_utils.c    | 520 +++++++++++++++++++++++
 src/daemon/common/nri/nri_utils.h    |   5 +-
 src/daemon/config/isulad_config.c    | 178 ++++++++
 src/daemon/modules/api/specs_api.h   |   5 +
 src/daemon/modules/spec/specs.c      |  32 +-
 src/daemon/nri/nri_adaption.h        |  46 +-
 src/daemon/nri/nri_helpers.cc        |  93 +++++
 src/daemon/nri/nri_helpers.h         |   2 +-
 src/utils/cpputils/transform.cc      |   2 +-
 12 files changed, 2002 insertions(+), 31 deletions(-)
 create mode 100644 src/daemon/common/nri/nri_convert.cc
 create mode 100644 src/daemon/common/nri/nri_spec.c
 create mode 100644 src/daemon/common/nri/nri_utils.c
 create mode 100644 src/daemon/nri/nri_helpers.cc

diff --git a/src/daemon/common/nri/nri_convert.cc b/src/daemon/common/nri/nri_convert.cc
new file mode 100644
index 00000000..7cce64ec
--- /dev/null
+++ b/src/daemon/common/nri/nri_convert.cc
@@ -0,0 +1,539 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ *     http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: zhongtao
+ * Create: 2024-03-16
+ * Description: provide nri convert functions
+ *********************************************************************************/
+
+#include "nri_convert.h"
+
+#include "container_api.h"
+#include "v1_cri_helpers.h"
+#include "path.h"
+#include "transform.h"
+#include "nri_utils.h"
+
+static int64_t DefaultOOMScoreAdj = 0;
+
+static bool NRILinuxCpuFromCRI(const runtime::v1::LinuxContainerResources &config, nri_linux_cpu &cpu)
+{
+    if (!config.cpuset_cpus().empty()) {
+        cpu.cpus = util_strdup_s(config.cpuset_cpus().c_str());
+    }
+
+    if (!config.cpuset_mems().empty()) {
+        cpu.mems = util_strdup_s(config.cpuset_mems().c_str());
+    }
+
+    cpu.period = (uint64_t *)util_common_calloc_s(sizeof(uint64_t));
+    if (cpu.period == nullptr) {
+        ERROR("Out of memory");
+        return false;
+    }
+    *(cpu.period) = config.cpu_period();
+
+    cpu.quota = (int64_t  *)util_common_calloc_s(sizeof(int64_t));
+    if (cpu.quota == nullptr) {
+        ERROR("Out of memory");
+        return false;
+    }
+    *(cpu.quota) = config.cpu_quota();
+
+    cpu.shares = (uint64_t *)util_common_calloc_s(sizeof(uint64_t));
+    if (cpu.shares == nullptr) {
+        ERROR("Out of memory");
+        return false;
+    }
+    *(cpu.shares) = config.cpu_shares();
+
+    // consistent with other container engines,
+    // not obtained cpu.realtime_period & cpu.realtime_runtime
+    return true;
+}
+
+static bool NRILinuxMemoryFromCRI(const runtime::v1::LinuxContainerResources &config, nri_linux_memory &memory)
+{
+    memory.limit = (int64_t *)util_common_calloc_s(sizeof(int64_t));
+    if (memory.limit == nullptr) {
+        ERROR("Out of memory");
+        return false;
+    }
+    *(memory.limit) = config.memory_limit_in_bytes();
+
+    // consistent with other container engines,
+    // not obtained other memory info
+
+    return true;
+}
+
+static bool NRIHugePageLimitFromCRI(const runtime::v1::LinuxContainerResources &config, nri_linux_resources &resources)
+{
+    int i;
+    nri_hugepage_limit *tmp = nullptr;
+
+    if (config.hugepage_limits_size() == 0) {
+        return true;
+    }
+
+    resources.hugepage_limits = (nri_hugepage_limit **)util_smart_calloc_s(sizeof(nri_hugepage_limit *),
+                                                                           config.hugepage_limits_size());
+    if (resources.hugepage_limits == nullptr) {
+        ERROR("Out of memory");
+        return false;
+    }
+
+    for (i = 0; i < config.hugepage_limits_size(); i++) {
+        tmp = (nri_hugepage_limit *)util_common_calloc_s(sizeof(nri_hugepage_limit));
+        if (tmp == nullptr) {
+            ERROR("Out of memory");
+            return false;
+        }
+        tmp->page_size = util_strdup_s(config.hugepage_limits(i).page_size().c_str());
+        tmp->limit = config.hugepage_limits(i).limit();
+        resources.hugepage_limits[i] = tmp;
+        resources.hugepage_limits_len++;
+        tmp = nullptr;
+    }
+    return true;
+}
+
+static auto NRILinuxResourcesFromCRI(const runtime::v1::LinuxContainerResources &config,
+                                     nri_linux_resources &resources) -> bool
+{
+    if (!NRILinuxMemoryFromCRI(config, *resources.memory)) {
+        ERROR("Failed to transform memory to nri for container");
+        return false;
+    }
+
+    if (!NRILinuxCpuFromCRI(config, *resources.cpu)) {
+        ERROR("Failed to transform cpu to nri for container");
+        return false;
+    }
+
+    if (!NRIHugePageLimitFromCRI(config, resources)) {
+        ERROR("Failed to transform hugepage limits to nri for container");
+        return false;
+    }
+
+    // resources.blockio_class is not support
+    // resources.rdt_class is not support
+    // They are not standard fields in oci spec
+
+    Errors tmpError;
+
+    resources.unified = Transform::ProtobufMapToJsonMapForString(config.unified(), tmpError);
+    if (resources.unified == nullptr) {
+        ERROR("Failed to transform unified to nri for container : %s", tmpError.GetMessage().c_str());
+        return false;
+    }
+
+    // resources.devices is not set in pod
+
+    return true;
+}
+
+static auto NRILinuxFromCRI(const runtime::v1::LinuxPodSandboxConfig &config, nri_linux_pod_sandbox &linux) -> bool
+{
+    if (!init_nri_linux_resources(&linux.pod_overhead)) {
+        ERROR("Failed to init nri linux overhead resources for pod");
+        return false;
+    }
+    if (!init_nri_linux_resources(&linux.pod_resources)) {
+        ERROR("Failed to init nri linux resources resources for pod");
+        return false;
+    }
+    if (config.has_overhead() && !NRILinuxResourcesFromCRI(config.overhead(), *linux.pod_overhead)) {
+        ERROR("Failed to transform overhead to nri for pod");
+        return false;
+    }
+
+    if (config.has_resources() && !NRILinuxResourcesFromCRI(config.resources(), *linux.pod_resources)) {
+        ERROR("Failed to transform resources to nri for pod");
+        return false;
+    }
+
+    linux.cgroup_parent = util_strdup_s(config.cgroup_parent().c_str());
+
+    // todo: other container engines get linux.cgroups_path/linux.resourses/linux.namespace from spec.linux,
+    // How does isulad get these values ​​from CRI module?
+    return true;
+}
+
+auto PodSandboxToNRI(const std::shared_ptr<const sandbox::Sandbox> &sandbox, nri_pod_sandbox &pod) -> bool
+{
+    container_t *cont = nullptr;
+    Errors tmpError;
+
+    cont = containers_store_get(sandbox->GetName().c_str());
+    if (cont != nullptr) {
+        pod.pid = container_state_get_pid(cont->state);
+        container_unref(cont);
+    }
+
+    pod.id = util_strdup_s(sandbox->GetId().c_str());
+    pod.name = util_strdup_s(sandbox->GetName().c_str());
+    if (sandbox->GetSandboxConfig().has_metadata()) {
+        pod.uid = util_strdup_s(sandbox->GetSandboxConfig().metadata().uid().c_str());
+        pod._namespace = util_strdup_s(sandbox->GetSandboxConfig().metadata().namespace_().c_str());
+    }
+
+
+    pod.labels = Transform::ProtobufMapToJsonMapForString(sandbox->GetSandboxConfig().labels(), tmpError);
+    if (pod.labels == nullptr) {
+        ERROR("Failed to transform labels to nri for pod : %s, : %s", pod.name, tmpError.GetMessage().c_str());
+        return false;
+    }
+
+    pod.annotations = Transform::ProtobufMapToJsonMapForString(sandbox->GetSandboxConfig().annotations(), tmpError);
+    if (pod.annotations == nullptr) {
+        ERROR("Failed to transform annotations to nri for pod : %s, : %s", pod.name, tmpError.GetMessage().c_str());
+        return false;
+    }
+
+    if (sandbox->GetSandboxConfig().has_linux()) {
+        pod.linux = (nri_linux_pod_sandbox *)util_common_calloc_s(sizeof(nri_linux_pod_sandbox));
+        if (pod.linux == nullptr) {
+            ERROR("Out of memory");
+            return false;
+        }
+        if (!NRILinuxFromCRI(sandbox->GetSandboxConfig().linux(), *pod.linux)) {
+            ERROR("Failed to transform linux to nri for pod : %s", pod.name);
+            return false;
+        }
+    }
+
+    pod.runtime_handler = util_strdup_s(sandbox->GetRuntimeHandle().c_str());
+
+    return true;
+}
+
+static auto CRIMountArrToNRI(const runtime::v1::ContainerConfig &containerConfig, nri_container &con) -> bool
+{
+    size_t i, len;
+
+    // get mount from cont
+    len = containerConfig.mounts_size();
+    if (len == 0) {
+        return true;
+    }
+    con.mounts = (nri_mount **)util_smart_calloc_s(sizeof(nri_mount *), len);
+    if (con.mounts == nullptr) {
+        ERROR("Out of memory");
+        return false;
+    }
+
+    nri_mount *tmp = nullptr;
+
+    for (i = 0; i < len; i++) {
+        tmp = (nri_mount *)util_common_calloc_s(sizeof(nri_mount));
+        if (tmp == nullptr) {
+            ERROR("Out of memory");
+            goto error_out;
+        }
+
+        if (containerConfig.mounts()[i].container_path().empty() || containerConfig.mounts()[i].host_path().empty()) {
+            ERROR("Mount path is empty");
+            goto error_out;
+        }
+
+        char path[PATH_MAX] = { 0 };
+        if (!util_clean_path(containerConfig.mounts()[i].container_path().c_str(), path, sizeof(path))) {
+            ERROR("Failed to get clean path for mount src path: %s", containerConfig.mounts()[i].container_path().c_str());
+            goto error_out;
+        }
+
+        tmp->destination = util_strdup_s(path);
+
+        if (!util_clean_path(containerConfig.mounts()[i].host_path().c_str(), path, sizeof(path))) {
+            ERROR("Failed to get clean path for mount src path: %s", containerConfig.mounts()[i].host_path().c_str());
+            goto error_out;
+        }
+        tmp->source = util_strdup_s(path);
+
+        if (util_array_append(&(tmp->options), "rbind") != 0) {
+            ERROR("Failed to append options");
+            goto error_out;
+        }
+
+        if (containerConfig.mounts()[i].propagation() == runtime::v1::PROPAGATION_PRIVATE) {
+            DEBUG("noop, private is default");
+            if (util_array_append(&(tmp->options), "rprivate") != 0) {
+                ERROR("Failed to append options");
+                goto error_out;
+            }
+        } else if (containerConfig.mounts()[i].propagation() == runtime::v1::PROPAGATION_BIDIRECTIONAL) {
+            if (util_array_append(&(tmp->options), "rshared") != 0) {
+                ERROR("Failed to append options");
+                goto error_out;
+            }
+        } else if (containerConfig.mounts()[i].propagation() == runtime::v1::PROPAGATION_HOST_TO_CONTAINER) {
+            if (util_array_append(&(tmp->options), "rslave") != 0) {
+                ERROR("Failed to append options");
+                goto error_out;
+            }
+        } else {
+            WARN("unknown propagation mode for hostPath %s", containerConfig.mounts()[i].host_path().c_str());
+            if (util_array_append(&(tmp->options), "rprivate") != 0) {
+                ERROR("Failed to append options");
+                goto error_out;
+            }
+        }
+
+        if (containerConfig.mounts()[i].readonly()) {
+            if (util_array_append(&(tmp->options), "ro") != 0) {
+                ERROR("Failed to append options");
+                goto error_out;
+            }
+        } else {
+            if (util_array_append(&(tmp->options), "rw") != 0) {
+                ERROR("Failed to append options");
+                goto error_out;
+            }
+        }
+
+        tmp->type = util_strdup_s("bind");
+
+        con.mounts[i] = tmp;
+        tmp = nullptr;
+        con.mounts_len++;
+    }
+    return true;
+
+error_out:
+    free_nri_mount(tmp);
+    return false;
+}
+
+static auto MountPointsElementToNRI(container_config_v2_common_config_mount_points *mp, nri_container &con) -> bool
+{
+    size_t i, len;
+    nri_mount *tmp = nullptr;
+
+    if (mp == nullptr || mp->len == 0) {
+        return true;
+    }
+    len = mp->len;
+
+    con.mounts = (nri_mount **)util_smart_calloc_s(sizeof(nri_mount *), len);
+    if (con.mounts == nullptr) {
+        ERROR("Out of memory");
+        return false;
+    }
+
+    for (i = 0; i < len; i++) {
+        tmp = (nri_mount *)util_common_calloc_s(sizeof(nri_mount));
+        char path[PATH_MAX] = { 0 };
+
+        if (!util_clean_path(mp->values[i]->destination, path, sizeof(path))) {
+            ERROR("Failed to get clean path for mount dest path: %s", mp->values[i]->destination);
+            goto error_out;
+        }
+        tmp->destination = util_strdup_s(path);
+
+        if (!util_clean_path(mp->values[i]->source, path, sizeof(path))) {
+            ERROR("Failed to get clean path for mount src path: %s", mp->values[i]->source);
+            goto error_out;
+        }
+        tmp->source = util_strdup_s(path);
+
+        if (util_array_append(&(tmp->options), "rbind") != 0) {
+            ERROR("Failed to append options");
+            goto error_out;
+        }
+        if (util_array_append(&(tmp->options), mp->values[i]->propagation) != 0) {
+            ERROR("Failed to append options");
+            goto error_out;
+        }
+
+        if (mp->values[i]->rw) {
+            if (util_array_append(&(tmp->options), "rw") != 0) {
+                ERROR("Failed to append options");
+                goto error_out;
+            }
+        } else {
+            if (util_array_append(&(tmp->options), "ro") != 0) {
+                ERROR("Failed to append options");
+                goto error_out;
+            }
+        }
+
+        tmp->type = util_strdup_s("bind");
+        con.mounts[i] = tmp;
+        con.mounts_len++;
+        tmp = nullptr;
+    }
+
+    return true;
+
+error_out:
+    free_nri_mount(tmp);
+    return false;
+}
+
+// container info is incomplete because container in excution is not created
+auto ContainerToNRIByConConfig(const runtime::v1::ContainerConfig &containerConfig, nri_container &con) -> bool
+{
+    // todo: can not get container id and state from containerConfig
+    if (containerConfig.has_metadata() && !containerConfig.metadata().name().empty()) {
+        con.name = util_strdup_s(containerConfig.metadata().name().c_str());
+    }
+
+    Errors tmpError;
+
+    con.labels = Transform::ProtobufMapToJsonMapForString(containerConfig.labels(), tmpError);
+    if (con.labels == nullptr) {
+        ERROR("Failed to transform labels to nri for con : %s, : %s", con.name, tmpError.GetMessage().c_str());
+        return false;
+    }
+
+    con.annotations = Transform::ProtobufMapToJsonMapForString(containerConfig.annotations(), tmpError);
+    if (con.annotations == nullptr) {
+        ERROR("Failed to transform annotations to nri for con : %s, : %s", con.name, tmpError.GetMessage().c_str());
+        return false;
+    }
+
+    con.args = Transform::RepeatedPtrFieldToCharArray(containerConfig.args());
+    if (con.args == nullptr) {
+        ERROR("Failed to transform args to nri for con : %s, : %s", con.name, tmpError.GetMessage().c_str());
+        return false;
+    }
+    con.args_len = containerConfig.args_size();
+
+    auto envVect = CRIHelpersV1::GenerateEnvList(containerConfig.envs());
+    con.env = Transform::StringVectorToCharArray(envVect);
+    if (con.env == nullptr) {
+        ERROR("Failed to transform env to nri for con : %s", con.name);
+        return false;
+    }
+    con.env_len = containerConfig.envs_size();
+
+    if (!CRIMountArrToNRI(containerConfig, con)) {
+        ERROR("Failed to transform mounts to nri for con : %s", con.name);
+        return false;
+    }
+    return true;
+
+    // todo: can not get container hooks and pid from containerConfig
+}
+
+// container info is incomplete because container in excution is not created
+auto ContainerToNRIByID(const std::string &id, nri_container &con) -> bool
+{
+    container_t *cont = nullptr;
+    bool ret = false;
+
+    cont = containers_store_get(id.c_str());
+    if (cont == nullptr || cont->common_config == nullptr) {
+        ERROR("No such container:%s", id.c_str());
+        goto out;
+    }
+
+    con.id = util_strdup_s(id.c_str());
+
+    con.name = util_strdup_s(cont->common_config->name);
+
+    con.labels = (json_map_string_string *)util_common_calloc_s(sizeof(json_map_string_string));
+    if (con.labels == nullptr) {
+        ERROR("Out of memory");
+        goto out;
+    }
+    con.annotations = (json_map_string_string *)util_common_calloc_s(sizeof(json_map_string_string));
+    if (con.annotations == nullptr) {
+        ERROR("Out of memory");
+        goto out;
+    }
+    // state
+    if (dup_json_map_string_string(cont->common_config->config->labels, con.labels) != 0) {
+        ERROR("Failed to copy labels for con: %s", cont->common_config->name);
+        goto out;
+    }
+    if (dup_json_map_string_string(cont->common_config->config->annotations, con.annotations) != 0) {
+        ERROR("Failed to copy labels for con: %s", cont->common_config->name);
+        goto out;
+    }
+
+    con.args = util_copy_array_by_len(cont->common_config->args, cont->common_config->args_len);
+    if (cont->common_config->args_len != 0 && con.args == nullptr) {
+        ERROR("Failed to copy args for con: %s", cont->common_config->name);
+        goto out;
+    }
+    con.args_len = cont->common_config->args_len;
+
+    con.env = util_copy_array_by_len(cont->common_config->config->env, cont->common_config->config->env_len);
+    if (cont->common_config->config->env_len != 0 && con.env == nullptr) {
+        ERROR("Failed to copy env for con: %s", cont->common_config->name);
+        goto out;
+    }
+    con.env_len = cont->common_config->config->env_len;
+
+    if (!MountPointsElementToNRI(cont->common_config->mount_points, con)) {
+        ERROR("Failed to transform mounts to nri for con : %s", con.name);
+        goto out;
+    }
+
+    // todo: can convert hostconfig's hook_spec to nri spec
+
+    con.pid = container_state_get_pid(cont->state);
+    if (con.pid < 0) {
+        ERROR("Container %s pid %d invalid", cont->common_config->name, con.pid);
+        goto out;
+    }
+
+    con.pod_sandbox_id = util_strdup_s(cont->common_config->sandbox_info->id);
+    ret = true;
+
+out:
+    container_unref(cont);
+    return ret;
+}
+
+auto LinuxResourcesFromNRI(const nri_linux_resources *src, runtime::v1::LinuxContainerResources &resources) -> bool
+{
+    if (src == nullptr) {
+        return false;
+    }
+
+    if (src->memory != nullptr) {
+        resources.set_memory_limit_in_bytes(*src->memory->limit);
+        resources.set_oom_score_adj(DefaultOOMScoreAdj);
+    }
+
+    if (src->cpu != nullptr) {
+        if (src->cpu->shares != NULL) {
+            resources.set_cpu_shares(*src->cpu->shares);
+        }
+        if (src->cpu->quota != NULL) {
+            resources.set_cpu_quota(*src->cpu->quota);
+        }
+        if (src->cpu->period != NULL) {
+            resources.set_cpu_period(*src->cpu->period);
+        }
+
+        resources.set_cpuset_cpus(src->cpu->cpus);
+        resources.set_cpuset_mems(src->cpu->mems);
+    }
+
+    if (src->hugepage_limits != nullptr && src->hugepage_limits_len > 0) {
+        for (size_t i = 0; i < src->hugepage_limits_len; i++) {
+            if (src->hugepage_limits[i] != nullptr) {
+                auto limit = resources.add_hugepage_limits();
+                limit->set_page_size(src->hugepage_limits[i]->page_size);
+                limit->set_limit(src->hugepage_limits[i]->limit);
+            }
+        }
+    }
+
+    if (src->unified != nullptr) {
+        Transform::JsonMapToProtobufMapForString(src->unified, *resources.mutable_unified());
+    }
+
+    return true;
+}
\ No newline at end of file
diff --git a/src/daemon/common/nri/nri_convert.h b/src/daemon/common/nri/nri_convert.h
index 883f7c41..c04b14e4 100644
--- a/src/daemon/common/nri/nri_convert.h
+++ b/src/daemon/common/nri/nri_convert.h
@@ -27,10 +27,11 @@
 #include "sandbox.h"
 #include "api_v1.pb.h"
 
-auto PodSandboxToNRI(const std::shared_ptr<const sandbox::Sandbox> &sandbox, nri_pod_sandbox *pod) -> bool;
-auto ContainerToNRIByConConfig(const runtime::v1::ContainerConfig &containerConfig, nri_container *con) -> bool;
-auto ContainerToNRIByID(const std::string &id, nri_container *con) -> bool;
-auto PodSandboxesToNRI(const std::vector<std::unique_ptr<sandbox::Sandbox>> &arrs, nri_pod_sandbox **pod, int pod_len) -> bool;
+auto PodSandboxToNRI(const std::shared_ptr<const sandbox::Sandbox> &sandbox, nri_pod_sandbox &pod) -> bool;
+auto ContainerToNRIByConConfig(const runtime::v1::ContainerConfig &containerConfig, nri_container &con) -> bool;
+auto ContainerToNRIByID(const std::string &id, nri_container &con) -> bool;
+auto PodSandboxesToNRI(const std::vector<std::unique_ptr<sandbox::Sandbox>> &arrs, nri_pod_sandbox **pod,
+                       int pod_len) -> bool;
 
 auto LinuxResourcesFromNRI(const nri_linux_resources *src, runtime::v1::LinuxContainerResources &resources) -> bool;
 #endif // DAEMON_COMMON_NRI_NRI_CONVERT_H
diff --git a/src/daemon/common/nri/nri_spec.c b/src/daemon/common/nri/nri_spec.c
new file mode 100644
index 00000000..855fe3b3
--- /dev/null
+++ b/src/daemon/common/nri/nri_spec.c
@@ -0,0 +1,602 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ *     http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: zhongtao
+ * Create: 2024-07-17
+ * Description: provide nri oci functions
+ *********************************************************************************/
+
+#include "nri_spec.h"
+
+#include <isula_libutils/log.h>
+
+#include "map.h"
+#include "utils.h"
+#include "utils_string.h"
+#include "nri_utils.h"
+#include "specs_api.h"
+#include "sysinfo.h"
+#include "verify.h"
+#include "specs_extend.h"
+
+static defs_hook *nri_hook_to_oci(const nri_hook *h)
+{
+    defs_hook *oci_hook = NULL;
+
+    if (h == NULL) {
+        return NULL;
+    }
+
+    oci_hook = util_common_calloc_s(sizeof(*oci_hook));
+    if (oci_hook == NULL) {
+        ERROR("Out of memory");
+        return NULL;
+    }
+
+    oci_hook->path = util_strdup_s(h->path);
+    if (h->args_len != 0) {
+        oci_hook->args = util_copy_array_by_len(h->args, h->args_len);
+        if (oci_hook->args == NULL) {
+            ERROR("Failed to copy args");
+            goto error_out;
+        }
+        oci_hook->args_len = h->args_len;
+    }
+    if (h->env_len != 0) {
+        oci_hook->env = util_copy_array_by_len(h->env, h->env_len);
+        if (oci_hook->env == NULL) {
+            ERROR("Failed to copy env");
+            goto error_out;
+        }
+        oci_hook->env_len = h->env_len;
+    }
+    if (h->timeout != NULL) {
+        oci_hook->timeout = *(h->timeout);
+    }
+    return oci_hook;
+
+error_out:
+    free_defs_hook(oci_hook);
+    return NULL;
+}
+
+static defs_device *nri_device_to_oci(nri_linux_device *dev)
+{
+    if (dev == NULL) {
+        return NULL;
+    }
+
+    defs_device *oci_dev = util_common_calloc_s(sizeof(defs_device));
+    if (oci_dev == NULL) {
+        ERROR("Out of memory");
+        return NULL;
+    }
+
+    oci_dev->path = util_strdup_s(dev->path);
+    oci_dev->type = util_strdup_s(dev->type);
+    oci_dev->major = dev->major;
+    oci_dev->minor = dev->minor;
+    if (dev->file_mode != NULL) {
+        oci_dev->file_mode = *dev->file_mode;
+    }
+    if (dev->uid != NULL) {
+        oci_dev->uid = *dev->uid;
+    }
+    if (dev->gid != NULL) {
+        oci_dev->gid = *dev->gid;
+    }
+
+    return oci_dev;
+}
+
+static defs_mount *nri_mount_to_oci(nri_mount *mount)
+{
+    if (mount == NULL) {
+        return NULL;
+    }
+
+    defs_mount *oci_mount = util_common_calloc_s(sizeof(defs_mount));
+    if (oci_mount == NULL) {
+        ERROR("Out of memory");
+        return NULL;
+    }
+
+    oci_mount->destination = util_strdup_s(mount->destination);
+    oci_mount->type = util_strdup_s(mount->type);
+    oci_mount->source = util_strdup_s(mount->source);
+    if (mount->options_len != 0) {
+        oci_mount->options = util_copy_array_by_len(mount->options, mount->options_len);
+        if (oci_mount->options == NULL) {
+            ERROR("Failed to copy options");
+            free_defs_mount(oci_mount);
+            return NULL;
+        }
+        oci_mount->options_len = mount->options_len;
+    }
+
+    return oci_mount;
+}
+
+static int nri_adjust_annotation(const nri_container_adjustment *adjust, oci_runtime_spec *oci_spec)
+{
+    int ret = -1;
+    size_t i;
+
+    if (adjust == NULL || adjust->annotations == NULL || adjust->annotations->len == 0) {
+        return 0;
+    }
+
+    if (make_sure_oci_spec_annotations(oci_spec) != 0) {
+        ERROR("Failed to make sure oci spec annotations");
+        return -1;
+    }
+
+    json_map_string_string *cleard = (json_map_string_string *)util_common_calloc_s(sizeof(json_map_string_string));
+    if (cleard == NULL) {
+        ERROR("Out of memory");
+        return -1;
+    }
+
+    map_t *del = map_new(MAP_STR_STR, MAP_DEFAULT_CMP_FUNC, MAP_DEFAULT_FREE_FUNC);
+    if (del == NULL) {
+        ERROR("Out of memory");
+        goto free_out;
+    }
+
+    for (i = 0; i < adjust->annotations->len; i++) {
+        __isula_auto_free char *out = NULL;
+        if (is_marked_for_removal(adjust->annotations->keys[i], &out)) {
+            if (!map_insert(del, out, "")) {
+                ERROR("Failed to insert del map");
+                goto free_out;
+            }
+            continue;
+        }
+        if (append_json_map_string_string(cleard, adjust->annotations->keys[i],
+                                          adjust->annotations->values[i]) != 0) {
+            ERROR("Failed to append annotation");
+            goto free_out;
+        }
+    }
+
+    for (i = 0; i < oci_spec->annotations->len; i++) {
+        if (map_search(del, oci_spec->annotations->keys[i]) != NULL) {
+            continue;
+        }
+        append_json_map_string_string(cleard, oci_spec->annotations->keys[i],
+                                      oci_spec->annotations->values[i]);
+    }
+
+    free_json_map_string_string(oci_spec->annotations);
+    oci_spec->annotations = cleard;
+    ret = 0;
+
+free_out:
+    free_json_map_string_string(cleard);
+    map_free(del);
+    return ret;
+}
+
+static void nri_key_value_map_kvfree(void *key, void *value)
+{
+    free(key);
+
+    // no need to free nri_key_value
+    // nri_key_value *value will be free in nri_container_adjustment *adjust
+}
+
+
+static int nri_adjust_env(const nri_container_adjustment *adjust, oci_runtime_spec *oci_spec)
+{
+    int ret = -1;
+    size_t i;
+    char **old_env = NULL;
+    size_t old_env_len = 0;
+    __isula_auto_array_t char **adjust_env = NULL;
+    size_t adjust_env_len = 0;
+
+    if (adjust->env == NULL || adjust->env_len == 0) {
+        return 0;
+    }
+
+    map_t *mod = map_new(MAP_STR_PTR, MAP_DEFAULT_CMP_FUNC, nri_key_value_map_kvfree);
+    if (mod == NULL) {
+        ERROR("Out of memory");
+        goto free_out;
+    }
+
+    for (i = 0; i < adjust->env_len; i++) {
+        nri_key_value *e = adjust->env[i];
+        char *out = NULL;
+        (void)is_marked_for_removal(e->key, &out);
+
+        if (!map_insert(mod, out, e) == false) {
+            ERROR("Failed to insert mod map");
+            goto free_out;
+        }
+    }
+
+    if (map_size(mod) <= 0 || oci_spec == NULL || oci_spec->process == NULL) {
+        ret = 0;
+        goto free_out;
+    }
+
+    // modify existing environment
+    old_env = oci_spec->process->env;
+    old_env_len = oci_spec->process->env_len;
+    oci_spec->process->env = NULL;
+    oci_spec->process->env_len = 0;
+
+    for (i = 0; i < old_env_len; i++) {
+        __isula_auto_array_t char **envArr = util_string_split_n(old_env[i], '=', 2);
+        if (envArr == NULL) {
+            continue;
+        }
+
+        nri_key_value *target = map_search(mod, envArr[0]);
+        if (target != NULL) {
+            __isula_auto_free char *out = NULL;
+            if (!is_marked_for_removal(envArr[0], &out)) {
+                // If not marked for removal, append modified value
+                __isula_auto_free char *tmp_str = util_string_append(target->key, "=");
+                __isula_auto_free char *final_str = util_string_append(tmp_str, target->value);
+
+                if (util_array_append(&adjust_env, final_str) != 0) {
+                    ERROR("Failed to append env");
+                    goto free_out;
+                }
+                adjust_env_len++;
+                continue;
+            }
+        }
+        // If not found in mod map, append original value
+        if (util_array_append(&adjust_env, old_env[i]) != 0) {
+            ERROR("Failed to append env");
+            goto free_out;
+        }
+        adjust_env_len++;
+    }
+
+    ret = 0;
+free_out:
+    if (merge_env(oci_spec, (const char **)adjust_env, adjust_env_len) != 0) {
+        ERROR("Failed to merge env");
+        goto free_out;
+    }
+    for (i = 0; i < old_env_len; i++) {
+        free(old_env[i]);
+    }
+    free(old_env);
+    map_free(mod);
+    return ret;
+}
+
+static int nri_adjust_hooks(const nri_container_adjustment *adjust, oci_runtime_spec *oci_spec)
+{
+    if (adjust->hooks == NULL) {
+        return 0;
+    }
+
+    size_t i;
+    int ret = 0;
+
+    if (make_sure_oci_spec_hooks(oci_spec) != 0) {
+        ERROR("Failed to make sure oci spec hooks");
+        return -1;
+    }
+
+    // todo: change to macro definition function call
+    for (i = 0; i < adjust->hooks->prestart_len; i++) {
+        defs_hook *oci_hook = nri_hook_to_oci(adjust->hooks->prestart[i]);
+        ret = spec_add_prestart_hook(oci_spec, oci_hook);
+        if (ret != 0) {
+            ERROR("Failed add hook %s", adjust->hooks->prestart[i]->path);
+            free_defs_hook(oci_hook);
+            return -1;
+        }
+    }
+
+    for (i = 0; i < adjust->hooks->poststart_len; i++) {
+        defs_hook *oci_hook = nri_hook_to_oci(adjust->hooks->poststart[i]);
+        ret = spec_add_poststart_hook(oci_spec, oci_hook);
+        if (ret != 0) {
+            ERROR("Failed add hook %s", adjust->hooks->poststart[i]->path);
+            free_defs_hook(oci_hook);
+            return -1;
+        }
+    }
+
+    for (i = 0; i < adjust->hooks->poststop_len; i++) {
+        defs_hook *oci_hook = nri_hook_to_oci(adjust->hooks->poststop[i]);
+        ret = spec_add_poststop_hook(oci_spec, oci_hook);
+        if (ret != 0) {
+            ERROR("Failed add hook %s", adjust->hooks->poststop[i]->path);
+            free_defs_hook(oci_hook);
+            return -1;
+        }
+    }
+    /*
+    * The OCI being used by the iSulad not supportes
+    * createRuntime/createContainer/startContainer currently.
+    */
+
+    return ret;
+}
+
+static int nri_adjust_devices(const nri_container_adjustment *adjust, oci_runtime_spec *oci_spec)
+{
+    if (adjust->linux == NULL || adjust->linux->devices == NULL || adjust->linux->devices_len == 0) {
+        return 0;
+    }
+
+    size_t i;
+
+    for (i = 0; i < adjust->linux->devices_len; i++) {
+        nri_linux_device *dev = adjust->linux->devices[i];
+        if (spec_add_device(oci_spec, nri_device_to_oci(dev)) != 0) {
+            ERROR("Failed to add device %s", dev->path);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static int nri_adjust_cgroup_path(const nri_container_adjustment *adjust, oci_runtime_spec *oci_spec)
+{
+    if (adjust->linux == NULL || adjust->linux->cgroups_path == NULL) {
+        return 0;
+    }
+
+    free(oci_spec->linux->cgroups_path);
+    oci_spec->linux->cgroups_path = util_strdup_s(adjust->linux->cgroups_path);
+
+    return 0;
+}
+
+static void nri_adjust_cpu_memory(nri_linux_resources *resource, oci_runtime_spec *oci_spec)
+{
+    if (resource->cpu == NULL) {
+        return;
+    }
+    if (make_sure_oci_spec_linux_resources_cpu(oci_spec) != 0) {
+        ERROR("Failed to make sure oci spec linux resources cpu");
+        return;
+    }
+    if (resource->cpu->shares != NULL) {
+        oci_spec->linux->resources->cpu->shares = *resource->cpu->shares;
+    }
+    if (resource->cpu->quota != NULL) {
+        oci_spec->linux->resources->cpu->quota = *resource->cpu->quota;
+    }
+    if (resource->cpu->period != NULL) {
+        oci_spec->linux->resources->cpu->period = *resource->cpu->period;
+    }
+    if (resource->cpu->realtime_runtime != NULL) {
+        oci_spec->linux->resources->cpu->realtime_runtime = *resource->cpu->realtime_runtime;
+    }
+    if (resource->cpu->realtime_period != NULL) {
+        oci_spec->linux->resources->cpu->realtime_period = *resource->cpu->realtime_period;
+    }
+}
+
+static void nri_adjust_memory_resource(nri_linux_resources *resource, oci_runtime_spec *oci_spec)
+{
+    if (resource->memory == NULL) {
+        return;
+    }
+
+    if (make_sure_oci_spec_linux_resources_mem(oci_spec) != 0) {
+        ERROR("Failed to make sure oci spec linux resources memory");
+        return;
+    }
+    if (resource->memory->limit != NULL) {
+        oci_spec->linux->resources->memory->limit = *resource->memory->limit;
+    }
+    if (resource->memory->reservation != NULL) {
+        oci_spec->linux->resources->memory->reservation = *resource->memory->reservation;
+    }
+    if (resource->memory->swap != NULL) {
+        oci_spec->linux->resources->memory->swap = *resource->memory->swap;
+    }
+    if (resource->memory->kernel != NULL) {
+        oci_spec->linux->resources->memory->kernel = *resource->memory->kernel;
+    }
+    if (resource->memory->kernel_tcp != NULL) {
+        oci_spec->linux->resources->memory->kernel_tcp = *resource->memory->kernel_tcp;
+    }
+    if (resource->memory->swappiness != NULL) {
+        oci_spec->linux->resources->memory->swappiness = *resource->memory->swappiness;
+    }
+    if (resource->memory->disable_oom_killer != NULL) {
+        oci_spec->linux->resources->memory->disable_oom_killer = *resource->memory->disable_oom_killer;
+    }
+}
+
+static int nri_adjust_hugepage_resource(nri_linux_resources *resource, oci_runtime_spec *oci_spec)
+{
+    size_t i;
+    if (resource->hugepage_limits != NULL) {
+        for (i = 0; i < resource->hugepage_limits_len; i++) {
+            nri_hugepage_limit *limit = resource->hugepage_limits[i];
+            if (limit->page_size != NULL) {
+                if (spec_add_linux_resources_hugepage_limit(oci_spec, limit->page_size, limit->limit) != 0) {
+                    ERROR("Failed to add hugepage limit");
+                    return -1;
+                }
+            }
+        }
+    }
+    return 0;
+}
+
+static int nri_adjust_unified_resource(nri_linux_resources *resource, oci_runtime_spec *oci_spec)
+{
+    size_t i;
+    if (resource->unified != NULL) {
+        for (i = 0; i < resource->unified->len; i++) {
+            if (append_json_map_string_string(oci_spec->linux->resources->unified, resource->unified->keys[i],
+                                              resource->unified->values[i]) != 0) {
+                ERROR("Failed to append unified resource");
+                return -1;
+            }
+        }
+    }
+    return 0;
+}
+
+static int nri_adjust_resources(const nri_container_adjustment *adjust, oci_runtime_spec *oci_spec)
+{
+    if (adjust->linux == NULL || adjust->linux->resources == NULL) {
+        return 0;
+    }
+
+    nri_linux_resources *resource = adjust->linux->resources;
+
+    nri_adjust_memory_resource(resource, oci_spec);
+    nri_adjust_cpu_memory(resource, oci_spec);
+
+    if (nri_adjust_hugepage_resource(resource, oci_spec) != 0) {
+        ERROR("Failed to adjust hugepage resource");
+        return -1;
+    }
+
+    if (nri_adjust_unified_resource(resource, oci_spec) != 0) {
+        ERROR("Failed to adjust unified resource");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int nri_adjust_mounts(const nri_container_adjustment *adjust, oci_runtime_spec *oci_spec)
+{
+    if (adjust->mounts == NULL || adjust->mounts_len == 0) {
+        return 0;
+    }
+
+    size_t i;
+    for (i = 0; i < adjust->mounts_len; i++) {
+        nri_mount *mount = adjust->mounts[i];
+        defs_mount *oci_mount = nri_mount_to_oci(mount);
+        if (oci_mount == NULL) {
+            ERROR("Failed to convert nri mount to oci mount");
+            return -1;
+        }
+        if (spec_add_mount(oci_spec, oci_mount) != 0) {
+            ERROR("Failed to add mount");
+            free_defs_mount(oci_mount);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static int nri_adjust_rlimit(const nri_container_adjustment *adjust, oci_runtime_spec *oci_spec)
+{
+    if (adjust->rlimits == NULL || adjust->rlimits_len == 0) {
+        return 0;
+    }
+
+    size_t i;
+    for (i = 0; i < adjust->rlimits_len; i++) {
+        nri_posix_rlimit *rlimit = adjust->rlimits[i];
+        if (rlimit->type == NULL) {
+            ERROR("Invalid rlimit type");
+            return -1;
+        }
+        if (spec_add_linux_resources_rlimit(oci_spec, rlimit->type, rlimit->soft, rlimit->hard) != 0) {
+            ERROR("Failed to add rlimit");
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+// todo: we do not support it blockio_class
+static int nri_adjust_blockio_class(const nri_container_adjustment *adjust, oci_runtime_spec *oci_spec)
+{
+    if (adjust->linux == NULL || adjust->linux->resources->blockio_class == NULL) {
+        return 0;
+    }
+
+    return 0;
+}
+
+int nri_adjust_oci_spec(const nri_container_adjustment *adjust, oci_runtime_spec *oci_spec)
+{
+    if (oci_spec == NULL || adjust == NULL) {
+        ERROR("Invalid input arguments");
+        return -1;
+    }
+
+    if (nri_adjust_annotation(adjust, oci_spec) != 0) {
+        ERROR("Failed to do nri adjust annotation in oci spec");
+        return -1;
+    }
+
+    if (nri_adjust_env(adjust, oci_spec) != 0) {
+        ERROR("Failed to do nri adjust env in oci spec");
+        return -1;
+    }
+
+    if (nri_adjust_hooks(adjust, oci_spec) != 0) {
+        ERROR("Failed to do nri adjust hooks in oci spec");
+        return -1;
+    }
+
+    if (nri_adjust_devices(adjust, oci_spec) != 0) {
+        ERROR("Failed to do nri adjust devices in oci spec");
+        return -1;
+    }
+
+    if (nri_adjust_cgroup_path(adjust, oci_spec) != 0) {
+        ERROR("Failed to do nri adjust cgroup path in oci spec");
+        return -1;
+    }
+
+    if (nri_adjust_resources(adjust, oci_spec) != 0) {
+        ERROR("Failed to do nri adjust resources in oci spec");
+        return -1;
+    }
+
+    if (nri_adjust_blockio_class(adjust, oci_spec) != 0) {
+        ERROR("Failed to do nri adjust blockio class in oci spec");
+        return -1;
+    }
+
+    // iSuald is not support IntelRdt
+    if (nri_adjust_mounts(adjust, oci_spec) != 0) {
+        ERROR("Failed to do nri adjust mount in oci spec");
+        return -1;
+    }
+
+    if (nri_adjust_rlimit(adjust, oci_spec) != 0) {
+        ERROR("Failed to do nri adjust rlimit in oci spec");
+        return -1;
+    }
+
+    __isula_auto_sysinfo_t sysinfo_t *sysinfo = NULL;
+
+    sysinfo = get_sys_info(true);
+    if (sysinfo == NULL) {
+        ERROR("Failed to get system info");
+        return -1;
+    }
+
+    if (verify_container_settings(oci_spec, sysinfo) != 0) {
+        ERROR("Failed to verify oci runtime spec settings after adjust by nri");
+        return -1;
+    }
+
+    return 0;
+}
\ No newline at end of file
diff --git a/src/daemon/common/nri/nri_utils.c b/src/daemon/common/nri/nri_utils.c
new file mode 100644
index 00000000..51054e32
--- /dev/null
+++ b/src/daemon/common/nri/nri_utils.c
@@ -0,0 +1,520 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ *     http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: zhongtao
+ * Create: 2024-07-17
+ * Description: provide nri utils functions
+ *********************************************************************************/
+
+#include "nri_utils.h"
+
+#include <isula_libutils/log.h>
+
+#include "utils.h"
+
+static bool copy_nri_hugepage_limit(const nri_hugepage_limit* src, nri_hugepage_limit** dest)
+{
+    if (src == NULL || dest == NULL) {
+        ERROR("Invalid input arguments");
+        return false;
+    }
+
+    *dest = (nri_hugepage_limit *)util_common_calloc_s(sizeof(nri_hugepage_limit));
+    if (*dest == NULL) {
+        ERROR("Out of memory");
+        return false;
+    }
+
+    (*dest)->limit = src->limit;
+    (*dest)->page_size = util_strdup_s(src->page_size);
+    return true;
+}
+
+static bool copy_nri_hook(const nri_hook *src, nri_hook **dest)
+{
+    if (src == NULL || dest == NULL) {
+        ERROR("Invalid input arguments");
+        return false;
+    }
+
+    *dest = (nri_hook *)util_common_calloc_s(sizeof(nri_hook));
+    if (dest == NULL) {
+        ERROR("Out of memory");
+        return false;
+    }
+    (*dest)->args = util_copy_array_by_len(src->args, src->args_len);
+    (*dest)->args_len = src->args_len;
+    (*dest)->env = util_copy_array_by_len(src->env, src->env_len);
+    (*dest)->env_len = src->env_len;
+    (*dest)->path = util_strdup_s(src->path);
+    return true;
+}
+
+static bool copy_nri_linux_device_cgroup(const nri_linux_device_cgroup *src, nri_linux_device_cgroup **dest)
+{
+    if (src == NULL || dest == NULL) {
+        ERROR("Invalid input arguments");
+        return false;
+    }
+
+    *dest = (nri_linux_device_cgroup *)util_common_calloc_s(sizeof(nri_linux_device_cgroup));
+    if (dest == NULL) {
+        ERROR("Out of memory");
+        return false;
+    }
+    (*dest)->allow = src->allow;
+    (*dest)->type = util_strdup_s(src->type);
+    (*dest)->major = (int64_t *)util_common_calloc_s(sizeof(int64_t));
+    if ((*dest)->major == NULL) {
+        ERROR("Out of memory");
+        return false;
+    }
+    (*dest)->minor = (int64_t *)util_common_calloc_s(sizeof(int64_t));
+    if ((*dest)->minor == NULL) {
+        ERROR("Out of memory");
+        return false;
+    }
+    (*dest)->access = util_strdup_s(src->access);
+    return true;
+}
+
+static bool copy_nri_linux_cpu(const nri_linux_cpu *src, nri_linux_cpu **dest)
+{
+    if (src == NULL || dest == NULL) {
+        ERROR("Invalid input arguments");
+        return false;
+    }
+
+    (*dest) = (nri_linux_cpu *)util_common_calloc_s(sizeof(nri_linux_cpu));
+    if ((*dest) == NULL) {
+        ERROR("Out of memory");
+        return false;
+    }
+    (*dest)->cpus = util_strdup_s(src->cpus);
+    (*dest)->mems = util_strdup_s(src->mems);
+    if (src->period != NULL) {
+        (*dest)->period = (uint64_t *)util_common_calloc_s(sizeof(uint64_t));
+        if ((*dest)->period == NULL) {
+            ERROR("Out of memory");
+            return false;
+        }
+        *(*dest)->period = *src->period;
+    }
+
+    if (src->quota != NULL) {
+        (*dest)->quota = (int64_t *)util_common_calloc_s(sizeof(int64_t));
+        if ((*dest)->quota == NULL) {
+            ERROR("Out of memory");
+            return false;
+        }
+        *(*dest)->quota = *src->quota;
+    }
+
+    if (src->realtime_period != NULL) {
+        (*dest)->realtime_period = (uint64_t *)util_common_calloc_s(sizeof(uint64_t));
+        if ((*dest)->realtime_period == NULL) {
+            ERROR("Out of memory");
+            return false;
+        }
+        *(*dest)->realtime_period = *src->realtime_period;
+    }
+
+    if (src->realtime_runtime != NULL) {
+        (*dest)->realtime_runtime = (int64_t *)util_common_calloc_s(sizeof(int64_t));
+        if ((*dest)->realtime_runtime == NULL) {
+            ERROR("Out of memory");
+            return false;
+        }
+        *(*dest)->realtime_runtime = *src->realtime_runtime;
+    }
+
+    if (src->shares != NULL) {
+        (*dest)->shares = (uint64_t *)util_common_calloc_s(sizeof(uint64_t));
+        if ((*dest)->shares == NULL) {
+            ERROR("Out of memory");
+            return false;
+        }
+        *(*dest)->shares = *src->shares;
+    }
+
+    return true;
+}
+
+static bool copy_nri_linux_memory(const nri_linux_memory *src, nri_linux_memory **dest)
+{
+    if (src == NULL || dest == NULL) {
+        ERROR("Invalid input arguments");
+        return false;
+    }
+    *dest = (nri_linux_memory *)util_common_calloc_s(sizeof(nri_linux_memory));
+    if (dest == NULL) {
+        ERROR("Out of memory");
+        return false;
+    }
+    if (src->limit != NULL) {
+        (*dest)->limit = (int64_t *)util_common_calloc_s(sizeof(int64_t));
+        if ((*dest)->limit == NULL) {
+            ERROR("Out of memory");
+            return false;
+        }
+        *(*dest)->limit = *src->limit;
+    }
+
+    if (src->reservation != NULL) {
+        (*dest)->reservation = (int64_t *)util_common_calloc_s(sizeof(int64_t));
+        if ((*dest)->reservation == NULL) {
+            ERROR("Out of memory");
+            return false;
+        }
+        *(*dest)->reservation = *src->reservation;
+    }
+
+    if (src->swap != NULL) {
+        (*dest)->swap = (int64_t *)util_common_calloc_s(sizeof(int64_t));
+        if ((*dest)->swap == NULL) {
+            ERROR("Out of memory");
+            return false;
+        }
+        *(*dest)->swap = *src->swap;
+    }
+
+    if (src->kernel != NULL) {
+        (*dest)->kernel = (int64_t *)util_common_calloc_s(sizeof(int64_t));
+        if ((*dest)->kernel == NULL) {
+            ERROR("Out of memory");
+            return false;
+        }
+        *(*dest)->kernel = *src->kernel;
+    }
+
+
+    if (src->kernel_tcp != NULL) {
+        (*dest)->kernel_tcp = (int64_t *)util_common_calloc_s(sizeof(int64_t));
+        if ((*dest)->kernel_tcp == NULL) {
+            ERROR("Out of memory");
+            return false;
+        }
+        *(*dest)->kernel_tcp = *src->kernel_tcp;
+    }
+
+    if (src->swappiness != NULL) {
+        (*dest)->swappiness = (uint64_t *)util_common_calloc_s(sizeof(uint64_t));
+        if ((*dest)->swappiness == NULL) {
+            ERROR("Out of memory");
+            return false;
+        }
+        *(*dest)->swappiness = *src->swappiness;
+    }
+
+    if (src->disable_oom_killer != NULL) {
+        (*dest)->disable_oom_killer = (uint8_t *)util_common_calloc_s(sizeof(uint8_t));
+        if ((*dest)->disable_oom_killer == NULL) {
+            ERROR("Out of memory");
+            return false;
+        }
+        *(*dest)->disable_oom_killer = *src->disable_oom_killer;
+    }
+
+    if (src->use_hierarchy != NULL) {
+        (*dest)->use_hierarchy = (uint8_t *)util_common_calloc_s(sizeof(uint8_t));
+        if ((*dest)->use_hierarchy == NULL) {
+            ERROR("Out of memory");
+            return false;
+        }
+        *(*dest)->use_hierarchy = *src->use_hierarchy;
+    }
+    return true;
+}
+
+bool is_marked_for_removal(const char* key, char **out)
+{
+    if (key == NULL || out == NULL) {
+        ERROR("Invalid input arguments");
+        return false;
+    }
+
+    if (!util_has_prefix(key, "-")) {
+        *out = (char*)key;
+        return false;
+    }
+
+    *out = util_sub_string(key, 1, strlen(key) - 1);
+    if (*out == NULL) {
+        ERROR("Failed to sub string");
+        return false;
+    }
+
+    return true;
+}
+
+bool copy_nri_mount(const nri_mount *src, nri_mount **dest)
+{
+    if (src == NULL || dest == NULL) {
+        ERROR("Invalid input arguments");
+        return false;
+    }
+    *dest = (nri_mount *)util_common_calloc_s(sizeof(nri_mount));
+    if (dest == NULL) {
+        ERROR("Out of memory");
+        return false;
+    }
+    (*dest)->destination = util_strdup_s(src->destination);
+    (*dest)->options = util_copy_array_by_len(src->options, src->options_len);
+    (*dest)->options_len = src->options_len;
+    (*dest)->source = util_strdup_s(src->source);
+    (*dest)->type = util_strdup_s(src->type);
+    return true;
+}
+
+bool copy_nri_key_value(const nri_key_value *src, nri_key_value **dest)
+{
+    if (src == NULL || dest == NULL) {
+        ERROR("Invalid input arguments");
+        return false;
+    }
+    *dest = (nri_key_value *)util_common_calloc_s(sizeof(nri_key_value));
+    if (dest == NULL) {
+        ERROR("Out of memory");
+        return false;
+    }
+    (*dest)->key = util_strdup_s(src->key);
+    (*dest)->value = util_strdup_s(src->value);
+    return true;
+}
+
+bool copy_nri_posix_rlimit(const nri_posix_rlimit *src, nri_posix_rlimit **dest)
+{
+    if (src == NULL || dest == NULL) {
+        ERROR("Invalid input arguments");
+        return false;
+    }
+    *dest = (nri_posix_rlimit *)util_common_calloc_s(sizeof(nri_posix_rlimit));
+    if (dest == NULL) {
+        ERROR("Out of memory");
+        return false;
+    }
+    (*dest)->hard = src->hard;
+    (*dest)->soft = src->soft;
+    (*dest)->type = util_strdup_s(src->type);
+    return true;
+}
+
+bool copy_nri_linux_resources(const nri_linux_resources *src, nri_linux_resources **dest)
+{
+    if (src == NULL || dest == NULL) {
+        ERROR("Invalid input arguments");
+        return false;
+    }
+
+    *dest = (nri_linux_resources *)util_common_calloc_s(sizeof(nri_linux_resources));
+    if (*dest == NULL) {
+        ERROR("Out of memory");
+        return false;
+    }
+
+    if (!init_nri_linux_resources(dest)) {
+        ERROR("Failed to init dest nri linux resources");
+        goto free_out;
+    }
+
+    if (!copy_nri_linux_cpu(src->cpu, &(*dest)->cpu)) {
+        ERROR("Failed to copy nri_linux_cpu");
+        goto free_out;
+    }
+
+    if (!copy_nri_linux_memory(src->memory, &(*dest)->memory)) {
+        ERROR("Failed to copy nri_linux_memory");
+        goto free_out;
+    }
+
+    (*dest)->blockio_class = util_strdup_s(src->blockio_class);
+    (*dest)->rdt_class = util_strdup_s(src->rdt_class);
+
+    if (src->hugepage_limits_len > 0) {
+        (*dest)->hugepage_limits = (nri_hugepage_limit**)util_smart_calloc_s(sizeof(nri_hugepage_limit*),
+                                                                             src->hugepage_limits_len);
+        for (size_t i = 0; i < src->hugepage_limits_len; ++i) {
+            if (!copy_nri_hugepage_limit(src->hugepage_limits[i], &((*dest)->hugepage_limits[i]))) {
+                ERROR("Failed to copy nri_hugepage_limit");
+                goto free_out;
+            }
+        }
+    }
+
+    if (src->devices_len > 0) {
+        (*dest)->devices = (nri_linux_device_cgroup**)util_smart_calloc_s(sizeof(nri_linux_device_cgroup*), src->devices_len);
+        for (size_t i = 0; i < src->devices_len; ++i) {
+            if (!copy_nri_linux_device_cgroup(src->devices[i], &((*dest)->devices[i]))) {
+                ERROR("Failed to copy nri_linux_device_cgroup");
+                goto free_out;
+            }
+        }
+    }
+
+    if (dup_json_map_string_string(src->unified, (*dest)->unified)) {
+        ERROR("Failed to copy json_map_string_string");
+        goto free_out;
+    }
+
+    return true;
+
+free_out:
+    free_nri_linux_resources(*dest);
+    return false;
+}
+
+bool merge_nri_hooks(nri_hook **targetHooks, size_t targetSize, const nri_hook **sourceHooks,
+                     size_t sourceLen)
+{
+    size_t oldSize = targetSize * sizeof(nri_hook *);
+    size_t newSize = oldSize + sourceLen * sizeof(nri_hook *);
+
+    if (sourceHooks == NULL || targetHooks == NULL) {
+        ERROR("Invalid input arguments");
+        return false;
+    }
+
+    if (util_mem_realloc((void**)&targetHooks, newSize, (void**)&targetHooks, oldSize) != 0) {
+        ERROR("Failed to realloc and assign hook array");
+        return false;
+    }
+
+    for (size_t i = 0; i < sourceLen; i++) {
+        if (!copy_nri_hook(sourceHooks[i], &targetHooks[targetSize++])) {
+            ERROR("Failed to copy hook");
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool init_nri_container_adjust(nri_container_adjustment **adjust)
+{
+    if (adjust == NULL) {
+        ERROR("Invalid input arguments");
+        return false;
+    }
+
+    *adjust = (nri_container_adjustment *)util_common_calloc_s(sizeof(nri_container_adjustment));
+    if (*adjust == NULL) {
+        ERROR("Out of memory");
+        return false;
+    }
+
+    (*adjust)->annotations = (json_map_string_string *)util_common_calloc_s(sizeof(json_map_string_string));
+    if ((*adjust)->annotations == NULL) {
+        goto free_out;
+    }
+
+    (*adjust)->env = (nri_key_value **)util_common_calloc_s(sizeof(nri_key_value *));
+    if ((*adjust)->env == NULL) {
+        goto free_out;
+    }
+    (*adjust)->env_len = 0;
+
+    (*adjust)->hooks = (nri_hooks *)util_common_calloc_s(sizeof(nri_hooks));
+    if ((*adjust)->hooks == NULL) {
+        goto free_out;
+    }
+
+    (*adjust)->linux = (nri_linux_container_adjustment *)util_common_calloc_s(sizeof(nri_linux_container_adjustment));
+    if ((*adjust)->linux == NULL) {
+        goto free_out;
+    }
+
+    (*adjust)->linux->resources = (nri_linux_resources *)util_common_calloc_s(sizeof(nri_linux_resources));
+    if ((*adjust)->linux->resources == NULL) {
+        ERROR("Out of memory");
+        return false;
+    }
+
+    (*adjust)->mounts = (nri_mount **)util_common_calloc_s(sizeof(nri_mount *));
+    if ((*adjust)->mounts == NULL) {
+        goto free_out;
+    }
+    (*adjust)->mounts_len = 0;
+
+    (*adjust)->rlimits = (nri_posix_rlimit **)util_common_calloc_s(sizeof(nri_posix_rlimit *));
+    if ((*adjust)->rlimits == NULL) {
+        goto free_out;
+    }
+    (*adjust)->rlimits_len = 0;
+
+    return true;
+
+free_out:
+    ERROR("Out of memory");
+    free_nri_container_adjustment(*adjust);
+    return false;
+}
+
+bool init_nri_container_update(nri_container_update **update, const char *id, uint8_t ignore_failure)
+{
+    if (update == NULL || id == NULL) {
+        ERROR("Invalid input arguments");
+        return false;
+    }
+
+    *update = (nri_container_update *)util_common_calloc_s(sizeof(nri_container_update));
+    if (*update == NULL) {
+        ERROR("Out of memory");
+        return false;
+    }
+
+    (*update)->container_id = util_strdup_s(id);
+    (*update)->linux = (nri_linux_container_update *)util_common_calloc_s(sizeof(nri_linux_container_update));
+    if ((*update)->linux == NULL) {
+        goto free_out;
+    }
+
+    (*update)->ignore_failure = ignore_failure;
+    return true;
+
+free_out:
+    ERROR("Out of memory");
+    free_nri_container_update(*update);
+    return false;
+}
+
+bool init_nri_linux_resources(nri_linux_resources **resources)
+{
+    if (resources == NULL) {
+        ERROR("Invalid input arguments");
+        return false;
+    }
+
+    *resources = (nri_linux_resources *)util_common_calloc_s(sizeof(nri_linux_resources));
+    if (*resources == NULL) {
+        ERROR("Out of memory");
+        return false;
+    }
+
+    (*resources)->cpu = (nri_linux_cpu *)util_common_calloc_s(sizeof(nri_linux_cpu));
+    if ((*resources)->cpu == NULL) {
+        goto free_out;
+    }
+
+    (*resources)->memory = (nri_linux_memory *)util_common_calloc_s(sizeof(nri_linux_memory));
+    if ((*resources)->memory == NULL) {
+        goto free_out;
+    }
+
+    (*resources)->unified = (json_map_string_string *)util_common_calloc_s(sizeof(json_map_string_string));
+    if ((*resources)->unified == NULL) {
+        goto free_out;
+    }
+    return true;
+
+free_out:
+    ERROR("Out of memory");
+    free_nri_linux_resources(*resources);
+    return false;
+}
\ No newline at end of file
diff --git a/src/daemon/common/nri/nri_utils.h b/src/daemon/common/nri/nri_utils.h
index 3aa50ae4..7bf54a71 100644
--- a/src/daemon/common/nri/nri_utils.h
+++ b/src/daemon/common/nri/nri_utils.h
@@ -51,14 +51,13 @@ typedef enum {
 
 bool copy_nri_mount(const nri_mount *src, nri_mount **dest);
 bool copy_nri_key_value(const nri_key_value *src, nri_key_value **dest);
-bool copy_nri_hook(const nri_hook *src, nri_hook **dest);
 bool copy_nri_posix_rlimit(const nri_posix_rlimit *src, nri_posix_rlimit **dest);
 bool copy_nri_linux_resources(const nri_linux_resources *src, nri_linux_resources **dest);
-bool copy_nri_linux_cpu(const nri_linux_cpu *src, nri_linux_cpu **dest);
 
 bool is_marked_for_removal(const char* key, char **out);
 
-bool realloc_and_copy_nri_hooks(nri_hook **targetHooks, size_t targetSize, const nri_hook **sourceHooks, size_t sourceLen);
+bool merge_nri_hooks(nri_hook **targetHooks, size_t targetSize, const nri_hook **sourceHooks,
+                     size_t sourceLen);
 
 bool init_nri_container_adjust(nri_container_adjustment **adjust);
 bool init_nri_container_update(nri_container_update **update, const char *id, uint8_t ignore_failure);
diff --git a/src/daemon/config/isulad_config.c b/src/daemon/config/isulad_config.c
index d7b54498..9ba1c8a0 100644
--- a/src/daemon/config/isulad_config.c
+++ b/src/daemon/config/isulad_config.c
@@ -456,6 +456,175 @@ out:
     (void)isulad_server_conf_unlock();
     return path;
 }
+
+#ifdef ENABLE_NRI
+bool conf_get_nri_support(void)
+{
+    bool nri_support = false;
+    struct service_arguments *conf = NULL;
+
+    if (isulad_server_conf_rdlock() != 0) {
+        return false;
+    }
+
+    conf = conf_get_server_conf();
+    if (conf == NULL || conf->json_confs == NULL) {
+        goto out;
+    }
+
+    nri_support = conf->json_confs->nri_support;
+
+out:
+    (void)isulad_server_conf_unlock();
+    return nri_support;
+}
+
+bool conf_get_nri_external_support(void)
+{
+    bool nri_external_support = false;
+    struct service_arguments *conf = NULL;
+
+    if (isulad_server_conf_rdlock() != 0) {
+        return false;
+    }
+
+    conf = conf_get_server_conf();
+    if (conf == NULL || conf->json_confs == NULL) {
+        goto out;
+    }
+
+    nri_external_support = conf->json_confs->disable_connections;
+
+out:
+    (void)isulad_server_conf_unlock();
+    return !nri_external_support;
+}
+
+char *conf_get_nri_plugin_config_path(void)
+{
+    char *path = NULL;
+    struct service_arguments *conf = NULL;
+
+    if (isulad_server_conf_rdlock() != 0) {
+        return NULL;
+    }
+
+    conf = conf_get_server_conf();
+    if (conf == NULL || conf->json_confs == NULL || conf->json_confs->plugin_config_path == NULL) {
+        path = util_strdup_s(DEFAULT_PLUGIN_CONFIG_PATH);
+        goto out;
+    }
+
+    path = util_strdup_s(conf->json_confs->plugin_config_path);
+
+out:
+    (void)isulad_server_conf_unlock();
+    return path;
+}
+
+char *conf_get_nri_plugin_path(void)
+{
+    char *path = NULL;
+    struct service_arguments *conf = NULL;
+
+    if (isulad_server_conf_rdlock() != 0) {
+        return NULL;
+    }
+
+    conf = conf_get_server_conf();
+    if (conf == NULL || conf->json_confs == NULL) {
+        goto out;
+    }
+
+    if (conf->json_confs->plugin_path == NULL) {
+        path = util_strdup_s(DEFAULT_PLUGIN_PATH);
+        goto out;
+    }
+
+    path = util_strdup_s(conf->json_confs->plugin_path);
+
+out:
+    (void)isulad_server_conf_unlock();
+    return path;
+}
+
+char *conf_get_socket_path(void)
+{
+    char *path = NULL;
+    struct service_arguments *conf = NULL;
+
+    if (isulad_server_conf_rdlock() != 0) {
+        return NULL;
+    }
+
+    conf = conf_get_server_conf();
+    if (conf == NULL || conf->json_confs == NULL) {
+        goto out;
+    }
+
+    if (conf->json_confs->nri_socket_path == NULL) {
+        path = util_strdup_s(DEFAULT_SOCKET_PATH);
+        goto out;
+    }
+
+    path = util_strdup_s(conf->json_confs->nri_socket_path);
+
+out:
+    (void)isulad_server_conf_unlock();
+    return path;
+}
+
+uint64_t conf_get_nri_plugin_registration_timeout(void)
+{
+    uint64_t timeout = false;
+    struct service_arguments *conf = NULL;
+
+    if (isulad_server_conf_rdlock() != 0) {
+        return false;
+    }
+
+    conf = conf_get_server_conf();
+    if (conf == NULL || conf->json_confs == NULL) {
+        goto out;
+    }
+
+    if (conf->json_confs->plugin_registration_timeout == 0) {
+        timeout = DEFAULT_PLUGIN_REGISTRY_TIMEOUT;
+        goto out;
+    }
+
+    timeout = conf->json_confs->plugin_registration_timeout;
+
+out:
+    (void)isulad_server_conf_unlock();
+    return timeout;
+}
+uint64_t conf_get_nri_plugin_requst_timeout(void)
+{
+    uint64_t timeout = false;
+    struct service_arguments *conf = NULL;
+
+    if (isulad_server_conf_rdlock() != 0) {
+        return false;
+    }
+
+    conf = conf_get_server_conf();
+    if (conf == NULL || conf->json_confs == NULL) {
+        goto out;
+    }
+
+    if (conf->json_confs->plugin_requst_timeout == 0) {
+        timeout = DEFAULT_PLUGIN_REQUST_TIMEOUT;
+        goto out;
+    }
+
+    timeout = conf->json_confs->plugin_requst_timeout;
+
+out:
+    (void)isulad_server_conf_unlock();
+    return timeout;
+}
+#endif
 #endif
 
 /* conf get isulad rootdir */
@@ -1762,6 +1931,15 @@ int merge_json_confs_into_global(struct service_arguments *args)
     tmp_json_confs->cri_sandboxers = NULL;
 #endif
     args->json_confs->enable_cri_v1 = tmp_json_confs->enable_cri_v1;
+#ifdef ENABLE_NRI
+    args->json_confs->nri_support = tmp_json_confs->nri_support;
+    args->json_confs->disable_connections = tmp_json_confs->disable_connections;
+    override_string_value(&args->json_confs->plugin_config_path, &tmp_json_confs->plugin_config_path);
+    override_string_value(&args->json_confs->plugin_path, &tmp_json_confs->plugin_path);
+    args->json_confs->plugin_registration_timeout = tmp_json_confs->plugin_registration_timeout;
+    args->json_confs->plugin_requst_timeout = tmp_json_confs->plugin_requst_timeout;
+    override_string_value(&args->json_confs->nri_socket_path, &tmp_json_confs->nri_socket_path);
+#endif
     args->json_confs->enable_pod_events = tmp_json_confs->enable_pod_events;
 #endif
 
diff --git a/src/daemon/modules/api/specs_api.h b/src/daemon/modules/api/specs_api.h
index 6a1cd776..d5ea0c7c 100644
--- a/src/daemon/modules/api/specs_api.h
+++ b/src/daemon/modules/api/specs_api.h
@@ -76,6 +76,11 @@ int spec_add_linux_resources_hugepage_limit(oci_runtime_spec *oci_spec, const ch
 int spec_add_linux_resources_rlimit(oci_runtime_spec *oci_spec, const char *type, uint64_t hard, uint64_t soft);
 #endif /* ENABLE_NRI */
 
+int make_sure_oci_spec_annotations(oci_runtime_spec *oci_spec);
+int make_sure_oci_spec_linux_resources_cpu(oci_runtime_spec *oci_spec);
+int make_sure_oci_spec_linux_resources_mem(oci_runtime_spec *oci_spec);
+int make_sure_oci_spec_hooks(oci_runtime_spec *oci_spec);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/daemon/modules/spec/specs.c b/src/daemon/modules/spec/specs.c
index 1fd9e5a8..002431d8 100644
--- a/src/daemon/modules/spec/specs.c
+++ b/src/daemon/modules/spec/specs.c
@@ -87,8 +87,11 @@ struct readonly_default_oci_spec {
 
 static struct readonly_default_oci_spec g_rdspec;
 
-static int make_sure_oci_spec_annotations(oci_runtime_spec *oci_spec)
+int make_sure_oci_spec_annotations(oci_runtime_spec *oci_spec)
 {
+    if (oci_spec == NULL) {
+        return -1;
+    }
     if (oci_spec->annotations == NULL) {
         oci_spec->annotations = util_common_calloc_s(sizeof(json_map_string_string));
         if (oci_spec->annotations == NULL) {
@@ -464,10 +467,14 @@ out:
     return ret;
 }
 
-static int make_sure_oci_spec_linux_resources_cpu(oci_runtime_spec *oci_spec)
+int make_sure_oci_spec_linux_resources_cpu(oci_runtime_spec *oci_spec)
 {
     int ret = 0;
 
+    if (oci_spec == NULL) {
+        return -1;
+    }
+
     ret = make_sure_oci_spec_linux_resources(oci_spec);
     if (ret < 0) {
         return -1;
@@ -589,10 +596,14 @@ out:
     return ret;
 }
 
-static int make_sure_oci_spec_linux_resources_mem(oci_runtime_spec *oci_spec)
+int make_sure_oci_spec_linux_resources_mem(oci_runtime_spec *oci_spec)
 {
     int ret = 0;
 
+    if (oci_spec == NULL) {
+        return -1;
+    }
+
     ret = make_sure_oci_spec_linux_resources(oci_spec);
     if (ret < 0) {
         return -1;
@@ -731,8 +742,11 @@ out:
     return ret;
 }
 
-static int make_sure_oci_spec_hooks(oci_runtime_spec *oci_spec)
+int make_sure_oci_spec_hooks(oci_runtime_spec *oci_spec)
 {
+    if (oci_spec == NULL) {
+        return -1;
+    }
     if (oci_spec->hooks == NULL) {
         oci_spec->hooks = util_common_calloc_s(sizeof(oci_runtime_spec_hooks));
         if (oci_spec->hooks == NULL) {
@@ -2827,6 +2841,11 @@ int spec_add_linux_resources_hugepage_limit(oci_runtime_spec *oci_spec, const ch
     int ret = 0;
     defs_resources_hugepage_limits_element *hugepage_limit = NULL;
 
+    if (oci_spec == NULL || page_size == NULL) {
+        ERROR("Invalid arguments");
+        return -1;
+    }
+
     ret = make_sure_oci_spec_linux_resources(oci_spec);
     if (ret < 0) {
         return -1;
@@ -2859,6 +2878,11 @@ int spec_add_linux_resources_rlimit(oci_runtime_spec *oci_spec, const char *type
     int ret = 0;
     defs_process_rlimits_element *rlimit = NULL;
 
+    if (oci_spec == NULL || type == NULL) {
+        ERROR("Invalid arguments");
+        return -1;
+    }
+
     ret = make_sure_oci_spec_linux_resources(oci_spec);
     if (ret < 0) {
         return -1;
diff --git a/src/daemon/nri/nri_adaption.h b/src/daemon/nri/nri_adaption.h
index 7f0640df..874662cf 100644
--- a/src/daemon/nri/nri_adaption.h
+++ b/src/daemon/nri/nri_adaption.h
@@ -46,7 +46,6 @@ public:
 
     auto GetSockpath(std::vector<std::string> &paths) -> bool;
 
-    // Stop plugins.
     auto StopPlugins() -> bool;
 
     void RemoveClosedPlugins();
@@ -58,19 +57,23 @@ public:
     auto RunPodSandbox(std::shared_ptr<const sandbox::Sandbox> sandbox, Errors &error) ->bool;
     auto StopPodSandbox(std::shared_ptr<const sandbox::Sandbox> sandbox, Errors &error) ->bool;
     auto RemovePodSandbox(std::shared_ptr<const sandbox::Sandbox> sandbox, Errors &error) ->bool;
-    auto CreateContainer(std::shared_ptr<const sandbox::Sandbox> sandbox, const std::string &conId, const runtime::v1::ContainerConfig &containerConfig, nri_container_adjustment **adjust, Errors &error) -> bool;
-    auto PostCreateContainer(const std::string &conId, Errors &error) ->bool;
-    auto UndoCreateContainer(std::shared_ptr<const sandbox::Sandbox> sandbox, const std::string &conId, Errors &error) -> bool;
-    auto StartContainer(const std::string &conId, Errors &error) ->bool;
-    auto PostStartContainer(const std::string &conId, Errors &error) ->bool;
-    auto UpdateContainer(const std::string &conId, Errors &error) ->bool;
-    auto PostUpdateContainer(const std::string &conId, Errors &error) ->bool;
-    auto StopContainer(const std::string &conId, Errors &error) ->bool;
-    auto RemoveContainer(const std::string &conId, Errors &error) ->bool;
-    auto StateChange(nri_state_change_event *evt, Errors &error) ->bool;
-    auto updateContainers(const nri_update_containers_request *req, nri_update_containers_response **resp) ->bool;
+    auto CreateContainer(std::shared_ptr<const sandbox::Sandbox> sandbox, const std::string &conId,
+                         const runtime::v1::ContainerConfig &containerConfig, nri_container_adjustment **adjust,
+                         Errors &error) -> bool;
+    auto PostCreateContainer(const std::string &conId, Errors &error) -> bool;
+    auto UndoCreateContainer(std::shared_ptr<const sandbox::Sandbox> sandbox, const std::string &conId,
+                             Errors &error) -> bool;
+    auto StartContainer(const std::string &conId, Errors &error) -> bool;
+    auto PostStartContainer(const std::string &conId, Errors &error) -> bool;
+    auto UpdateContainer(const std::string &conId, Errors &error) -> bool;
+    auto PostUpdateContainer(const std::string &conId, Errors &error) -> bool;
+    auto StopContainer(const std::string &conId, Errors &error) -> bool;
+    auto RemoveContainer(const std::string &conId, Errors &error) -> bool;
+    auto StateChange(nri_state_change_event *evt, Errors &error) -> bool;
+    auto updateContainers(const nri_update_containers_request *req, nri_update_containers_response **resp) -> bool;
 
     auto NewExternalPlugin(int fd) -> bool;
+
 private:
     NRIAdaptation() = default;
     NRIAdaptation(const NRIAdaptation &other) = delete;
@@ -86,18 +89,25 @@ private:
     auto SortPlugins() -> bool;
     void GetClosedPlugins(std::vector<std::string> &closedPlugin);
 
-    auto IsSupport() -> bool;
+    auto ApplyUpdates(const std::vector<nri_container_update *> &update, std::vector<nri_container_update *> &failed,
+                      bool getFailed, Errors &error) -> bool;
 
-    auto ApplyUpdates(const std::vector<nri_container_update *> &update, std::vector<nri_container_update *> &failed, bool getFailed,
-                    Errors &error) -> bool;
+    auto IsSupport() -> bool;
 
-    auto NRIPodSandbox(const std::shared_ptr<const sandbox::Sandbox> &sandbox, Errors& error) -> std::unique_ptr<CStructWrapper<nri_pod_sandbox>>;
-    auto NRIContainerByConConfig(const std::shared_ptr<const sandbox::Sandbox> &sandbox, const runtime::v1::ContainerConfig &containerConfig, Errors& error) -> std::unique_ptr<CStructWrapper<nri_container>>;
-    auto NRIContainerByID(const std::string &id, Errors& error) -> std::unique_ptr<CStructWrapper<nri_container>>;
+    auto NRIPodSandbox(const std::shared_ptr<const sandbox::Sandbox> &sandbox,
+                       Errors &error) -> std::unique_ptr<CStructWrapper<nri_pod_sandbox>>;
+    auto NRIContainerByConConfig(const std::shared_ptr<const sandbox::Sandbox> &sandbox,
+                                 const runtime::v1::ContainerConfig &containerConfig, Errors &error) -> std::unique_ptr<CStructWrapper<nri_container>>;
+    auto NRIContainerByID(const std::string &id, Errors &error) -> std::unique_ptr<CStructWrapper<nri_container>>;
 
     auto GetNRIPluginConfigPath(void) -> std::string;
     auto GetNRIPluginPath(void) -> std::string;
     auto GetNRISockPath(void) -> std::string;
+
+    void PluginsStateChange(nri_state_change_event *evt);
+    bool PluginsCreateContainer(nri_create_container_request *req, const std::string &conId, pluginResult &result);
+    bool PluginsUpdateContainer(nri_update_container_request *req, const std::string &conId, pluginResult &result);
+
 private:
     RWMutex m_mutex;
     static std::atomic<NRIAdaptation *> m_instance;
diff --git a/src/daemon/nri/nri_helpers.cc b/src/daemon/nri/nri_helpers.cc
new file mode 100644
index 00000000..ff9d67c1
--- /dev/null
+++ b/src/daemon/nri/nri_helpers.cc
@@ -0,0 +1,93 @@
+/******************************************************************************
+ * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved.
+ * iSulad licensed under the Mulan PSL v2.
+ * You can use this software according to the terms and conditions of the Mulan PSL v2.
+ * You may obtain a copy of Mulan PSL v2 at:
+ *     http://license.coscl.org.cn/MulanPSL2
+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
+ * PURPOSE.
+ * See the Mulan PSL v2 for more details.
+ * Author: zhongtao
+ * Create: 2024-07-13
+ * Description: provide nri helpers functions
+ *********************************************************************************/
+
+#include "nri_helpers.h"
+
+#include <isula_libutils/log.h>
+
+#include "utils.h"
+#include "isulad_config.h"
+
+namespace NRIHelpers {
+std::string MarkForRemoval(const std::string &key)
+{
+    return "-" + key;
+}
+
+auto GetPluginConfig(std::string &idx, std::string &name, std::string &config) -> bool
+{
+    __isula_auto_free char *plugin_path = NULL;
+
+    plugin_path = conf_get_nri_plugin_config_path();
+    if (plugin_path == NULL) {
+        return false;
+    }
+    std::string compleName = idx + "-" + name;
+    std::vector<std::string> dropIns = {
+        std::string(plugin_path) + "/" + compleName + ".conf",
+        std::string(plugin_path) + "/" + name + ".conf"
+    };
+
+    for (const std::string &path : dropIns) {
+        char buf[MAX_BUFFER_SIZE + 1] = { 0 };
+        __isula_auto_close int fd = util_open(path.c_str(), O_RDONLY, 0);
+        if (fd < 0) {
+            ERROR("Failed to open '%s'", path.c_str());
+            return false;
+        }
+        int len = util_read_nointr(fd, buf, sizeof(buf) - 1);
+        if (len < 0) {
+            SYSERROR("Failed to read nri plugin config : %s", path.c_str());
+            return false;
+        }
+        config = std::string(buf);
+        return true;
+    }
+    return true;
+}
+
+void GenerateRandomExternalName(std::string &ret)
+{
+    __isula_auto_free char *external_name = NULL;
+
+    external_name = (char *)util_smart_calloc_s(sizeof(char), (CONTAINER_ID_MAX_LEN + 1));
+    if (external_name == NULL) {
+        ERROR("Out of memory");
+        return;
+    }
+
+    if (util_generate_random_str(external_name, (size_t)CONTAINER_ID_MAX_LEN)) {
+        ERROR("Generate exec suffix failed");
+        return;
+    }
+
+    ret = std::string(external_name);
+}
+
+bool CheckPluginIndex(const std::string &idx)
+{
+    if (idx.length() != 2) {
+        ERROR("Invalid plugin index \"%s\", must be 2 digits", idx.c_str());
+        return false;
+    }
+
+    if (!std::isdigit(idx[0]) || !std::isdigit(idx[1])) {
+        ERROR("Invalid plugin index \"%s\", (not [0-9][0-9])", idx.c_str());
+        return false;
+    }
+
+    return true;
+}
+}// namespace NRIHelpers
\ No newline at end of file
diff --git a/src/daemon/nri/nri_helpers.h b/src/daemon/nri/nri_helpers.h
index 06ee8419..1a2f488e 100644
--- a/src/daemon/nri/nri_helpers.h
+++ b/src/daemon/nri/nri_helpers.h
@@ -37,7 +37,7 @@ std::string MarkForRemoval(const std::string &key);
 
 auto GetPluginConfig(std::string &idx, std::string &name, std::string &config) -> bool;
 
-std::string GenerateRandomExternalName(void);
+void GenerateRandomExternalName(std::string &ret);
 
 bool CheckPluginIndex(const std::string &idx);
 
diff --git a/src/utils/cpputils/transform.cc b/src/utils/cpputils/transform.cc
index 51c154fb..ba8c1f7a 100644
--- a/src/utils/cpputils/transform.cc
+++ b/src/utils/cpputils/transform.cc
@@ -97,7 +97,7 @@ auto RepeatedPtrFieldToCharArray(const google::protobuf::RepeatedPtrField<std::s
     if (result == nullptr) {
         return nullptr;
     }
-    size_t i {};
+    size_t i = 0;
     for (const auto &it : ptrs) {
         result[i++] = util_strdup_s(it.c_str());
     }
-- 
2.25.1

