1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/src-openeuler-iSulad

В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
0067-cdi-support-modules-container_edits-parser.patch 39 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
liuxu Отправлено 20.04.2024 05:00 b409779
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210
From d0442316761717849deb248b5da45240f7bb1d38 Mon Sep 17 00:00:00 2001
From: liuxu <liuxu156@huawei.com>
Date: Thu, 11 Apr 2024 11:01:44 +0800
Subject: [PATCH 67/69] cdi:support modules container_edits/parser
---
src/daemon/modules/api/specs_api.h | 13 +
.../device/cdi/behavior/cdi_container_edits.c | 622 +++++++++++++++++-
.../device/cdi/behavior/cdi_container_edits.h | 2 +-
.../device/cdi/behavior/parser/cdi_parser.c | 196 +++++-
.../device/cdi/behavior/parser/cdi_parser.h | 6 +-
src/daemon/modules/spec/specs.c | 230 +++++++
6 files changed, 1052 insertions(+), 17 deletions(-)
diff --git a/src/daemon/modules/api/specs_api.h b/src/daemon/modules/api/specs_api.h
index f54c0d31..0999836b 100644
--- a/src/daemon/modules/api/specs_api.h
+++ b/src/daemon/modules/api/specs_api.h
@@ -55,6 +55,19 @@ const oci_runtime_spec *get_readonly_default_oci_spec(bool system_container);
int spec_module_init(void);
+#ifdef ENABLE_CDI
+int defs_process_add_multiple_env(defs_process *dp, const char **envs, size_t env_len);
+int spec_add_multiple_process_env(oci_runtime_spec *oci_spec, const char **envs, size_t env_len);
+int spec_add_device(oci_runtime_spec *oci_spec, defs_device *device);
+int spec_add_linux_resources_device(oci_runtime_spec *oci_spec, bool allow, const char *dev_type,
+ int64_t major, int64_t minor, const char *access);
+void spec_remove_mount(oci_runtime_spec *oci_spec, const char *dest);
+int spec_add_mount(oci_runtime_spec *oci_spec, defs_mount *mnt);
+int spec_add_prestart_hook(oci_runtime_spec *oci_spec, defs_hook *prestart_hook);
+int spec_add_poststart_hook(oci_runtime_spec *oci_spec, defs_hook *poststart_hook);
+int spec_add_poststop_hook(oci_runtime_spec *oci_spec, defs_hook *poststop_hook);
+#endif /* ENABLE_CDI */
+
#ifdef __cplusplus
}
#endif
diff --git a/src/daemon/modules/device/cdi/behavior/cdi_container_edits.c b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.c
index 590118b1..816b9c2d 100644
--- a/src/daemon/modules/device/cdi/behavior/cdi_container_edits.c
+++ b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.c
@@ -14,36 +14,642 @@
******************************************************************************/
#include "cdi_container_edits.h"
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <isula_libutils/auto_cleanup.h>
+#include <isula_libutils/log.h>
+#include <isula_libutils/utils_array.h>
+
+#include "error.h"
+#include "path.h"
+#include "specs_extend.h"
+#include "utils.h"
+#include "utils_array.h"
+#include "specs_api.h"
+
+/*
+ * The OCI being used by the iSulad not supportes
+ * createRuntime/createContainer/startContainer currently.
+ */
// PRESTART_HOOK is the name of the OCI "prestart" hook.
#define PRESTART_HOOK "prestart"
-// CREATE_RUNTIME_HOOK is the name of the OCI "createRuntime" hook.
-#define CREATE_RUNTIME_HOOK "createRuntime"
-// CREATE_CONTAINER_HOOK is the name of the OCI "createContainer" hook.
-#define CREATE_CONTAINER_HOOK "createContainer"
-// START_CONTAINER_HOOK is the name of the OCI "startContainer" hook.
-#define START_CONTAINER_HOOK "startContainer"
// POSTSTART_HOOK is the name of the OCI "poststart" hook.
#define POSTSTART_HOOK "poststart"
// POSTSTOP_HOOK is the name of the OCI "poststop" hook.
#define POSTSTOP_HOOK "poststop"
+#define VALID_HOOK_NAME_LEN 3
+static const char* g_valid_hook_names[VALID_HOOK_NAME_LEN] = {
+ PRESTART_HOOK, POSTSTART_HOOK, POSTSTOP_HOOK
+};
+
+static int cdi_validate_env(char **envs, size_t envs_len);
+static int cdi_validate_device_node(cdi_device_node *d);
+static int cdi_validate_hook(cdi_hook *h);
+static int cdi_validate_mount(cdi_mount *m);
+
+#define BLOCK_DEVICE "b"
+#define CHAR_DEVICE "c"
+#define FIFO_DEVICE "p"
+static int device_info_from_path(const char *path, char **dev_type, int64_t *major, int64_t *minor)
+{
+ struct stat stat = { 0 };
+ int ret = 0;
+
+ ret = lstat(path, &stat);
+ if (ret != 0) {
+ ERROR("Failed to stat %s", path);
+ return -1;
+ }
+
+ if (S_ISBLK(stat.st_mode)) {
+ *dev_type = util_strdup_s(BLOCK_DEVICE);
+ } else if (S_ISCHR(stat.st_mode)) {
+ *dev_type = util_strdup_s(CHAR_DEVICE);
+ } else if (S_ISFIFO(stat.st_mode)) {
+ *dev_type = util_strdup_s(FIFO_DEVICE);
+ } else {
+ *dev_type = NULL;
+ *major = 0;
+ *minor = 0;
+ ERROR("Not a device node");
+ return -1;
+ }
+
+ *major = (int64_t)major(stat.st_rdev);
+ *minor = (int64_t)minor(stat.st_rdev);
+ return 0;
+}
+
+static int fill_device_node_info(cdi_device_node *d)
+{
+ __isula_auto_free char *dev_type = NULL;
+ int64_t major;
+ int64_t minor;
+
+ if (d->host_path == NULL) {
+ d->host_path = util_strdup_s(d->path);
+ }
+
+ if (d->type != NULL && (d->major != 0 || strcmp(d->type, FIFO_DEVICE) == 0)) {
+ return 0;
+ }
+
+ if (device_info_from_path(d->host_path, &dev_type, &major, &minor) != 0) {
+ ERROR("Failed to stat CDI host device %s", d->host_path);
+ return -1;
+ }
+
+ if (d->type == NULL) {
+ d->type = dev_type;
+ dev_type = NULL;
+ } else {
+ if (strcmp(d->type, dev_type) != 0) {
+ ERROR("CDI device (%s, %s), host type mismatch (%s, %s)",
+ d->path, d->host_path, d->type, dev_type);
+ return -1;
+ }
+ }
+ if (d->major == 0 && strcmp(d->type, FIFO_DEVICE) != 0) {
+ d->major = major;
+ d->minor = minor;
+ }
+ return 0;
+}
+
+static cdi_device_node *clone_cdi_device_node(cdi_device_node *d)
+{
+ cdi_device_node *device_node = NULL;
+
+ device_node = util_common_calloc_s(sizeof(*device_node));
+ if (device_node == NULL) {
+ ERROR("Out of memory");
+ return NULL;
+ }
+
+ device_node->path = util_strdup_s(d->path);
+ device_node->host_path = util_strdup_s(d->host_path);
+ device_node->type = util_strdup_s(d->type);
+ device_node->major = d->major;
+ device_node->minor = d->minor;
+ device_node->file_mode = d->file_mode;
+ device_node->permissions = util_strdup_s(d->permissions);
+ device_node->uid = d->uid;
+ device_node->gid = d->gid;
+ return device_node;
+}
+
+static cdi_hook *clone_cdi_hook(cdi_hook *h)
+{
+ cdi_hook *hook = NULL;
+
+ hook = util_common_calloc_s(sizeof(*hook));
+ if (hook == NULL) {
+ ERROR("Out of memory");
+ return NULL;
+ }
+
+ hook->hook_name = util_strdup_s(h->hook_name);
+ hook->path = util_strdup_s(h->path);
+ if (h->args_len != 0) {
+ hook->args = util_copy_array_by_len(h->args, h->args_len);
+ if (hook->args == NULL) {
+ ERROR("Failed to copy args");
+ goto error_out;
+ }
+ hook->args_len = h->args_len;
+ }
+ if (h->env_len != 0) {
+ hook->env = util_copy_array_by_len(h->env, h->env_len);
+ if (hook->env == NULL) {
+ ERROR("Failed to copy env");
+ goto error_out;
+ }
+ hook->env_len = h->env_len;
+ }
+ hook->timeout = h->timeout;
+
+ return hook;
+
+error_out:
+ free_cdi_hook(hook);
+ return NULL;
+}
+
+static cdi_mount *clone_cdi_mount(cdi_mount *m)
+{
+ cdi_mount *mount = NULL;
+
+ mount = util_common_calloc_s(sizeof(*mount));
+ if (mount == NULL) {
+ ERROR("Out of memory");
+ return NULL;
+ }
+
+ mount->host_path = util_strdup_s(m->host_path);
+ mount->container_path = util_strdup_s(m->container_path);
+ if (m->options_len != 0) {
+ mount->options = util_copy_array_by_len(m->options, m->options_len);
+ if (mount->options == NULL) {
+ ERROR("Failed to copy options");
+ free_cdi_mount(mount);
+ return NULL;
+ }
+ mount->options_len = m->options_len;
+ }
+ mount->type = util_strdup_s(m->type);
+
+ return mount;
+}
+
+static defs_hook *cdi_hook_to_oci(cdi_hook *h)
+{
+ defs_hook *oci_hook = NULL;
+
+ oci_hook = util_common_calloc_s(sizeof(*oci_hook));
+ if (oci_hook == NULL) {
+ ERROR("Out of memory");
+ return NULL;
+ }
+
+ oci_hook->path = util_strdup_s(h->path);
+ if (h->args_len != 0) {
+ oci_hook->args = util_copy_array_by_len(h->args, h->args_len);
+ if (oci_hook->args == NULL) {
+ ERROR("Failed to copy args");
+ goto error_out;
+ }
+ oci_hook->args_len = h->args_len;
+ }
+ if (h->env_len != 0) {
+ oci_hook->env = util_copy_array_by_len(h->env, h->env_len);
+ if (oci_hook->env == NULL) {
+ ERROR("Failed to copy env");
+ goto error_out;
+ }
+ oci_hook->env_len = h->env_len;
+ }
+ oci_hook->timeout = h->timeout;
+ return oci_hook;
+
+error_out:
+ free_defs_hook(oci_hook);
+ return NULL;
+}
+
+static defs_mount *cdi_mount_to_oci(cdi_mount *m)
+{
+ defs_mount *oci_mount = NULL;
+
+ oci_mount = util_common_calloc_s(sizeof(*oci_mount));
+ if (oci_mount == NULL) {
+ ERROR("Out of memory");
+ return NULL;
+ }
+
+ oci_mount->source = util_strdup_s(m->host_path);
+ oci_mount->destination = util_strdup_s(m->container_path);
+ if (m->options_len != 0) {
+ oci_mount->options = util_copy_array_by_len(m->options, m->options_len);
+ if (oci_mount->options == NULL) {
+ ERROR("Failed to copy options");
+ free_defs_mount(oci_mount);
+ return NULL;
+ }
+ oci_mount->options_len = m->options_len;
+ }
+ oci_mount->type = util_strdup_s(m->type);
+
+ return oci_mount;
+}
+
+static defs_device *cdi_device_node_to_oci(cdi_device_node *d)
+{
+ defs_device *oci_device = NULL;
+
+ oci_device = util_common_calloc_s(sizeof(*oci_device));
+ if (oci_device == NULL) {
+ ERROR("Out of memory");
+ return NULL;
+ }
+
+ oci_device->path = util_strdup_s(d->path);
+ oci_device->type = util_strdup_s(d->type);
+ oci_device->major = d->major;
+ oci_device->minor = d->minor;
+ oci_device->file_mode = d->file_mode;
+ oci_device->uid = d->uid;
+ oci_device->gid = d->gid;
+
+ return oci_device;
+}
+
+static int apply_cdi_device_nodes(cdi_container_edits *e, oci_runtime_spec *spec)
+{
+ size_t i;
+ defs_device *dev = NULL;
+ cdi_device_node *dn = NULL;
+ const char *access = NULL;
+
+ for (i = 0; i < e->device_nodes_len; i++) {
+ dn = clone_cdi_device_node(e->device_nodes[i]);
+ if (dn == NULL) {
+ ERROR("Failed to copy device node");
+ goto error_out;
+ }
+
+ if (fill_device_node_info(dn) != 0) {
+ goto error_out;
+ }
+ dev = cdi_device_node_to_oci(dn);
+ if (dev == NULL) {
+ ERROR("Failed to generate oci device");
+ goto error_out;
+ }
+ /* Currently, for uid and gid, isulad cannot distinguish
+ * 0 and unspecified. Here, 0 is processed as unspecified.
+ */
+ if (dev->uid == 0 && spec->process != NULL) {
+ if (spec->process->user->uid > 0) {
+ dev->uid = spec->process->user->uid;
+ }
+ }
+ if (dev->gid == 0 && spec->process != NULL) {
+ if (spec->process->user->gid > 0) {
+ dev->gid = spec->process->user->gid;
+ }
+ }
+
+ if (spec_add_device(spec, dev) != 0) {
+ goto error_out;
+ }
+
+ if (strcmp(dev->type, BLOCK_DEVICE) == 0 || strcmp(dev->type, CHAR_DEVICE) == 0) {
+ if (e->device_nodes[i]->permissions != NULL) {
+ access = e->device_nodes[i]->permissions;
+ } else {
+ access = "rwm";
+ }
+ if (spec_add_linux_resources_device(spec, true, dev->type,
+ dev->major, dev->minor, access)) {
+ dev = NULL;
+ goto error_out;
+ }
+ }
+ free_cdi_device_node(dn);
+ dn = NULL;
+ dev = NULL;
+ }
+
+ return 0;
+
+error_out:
+ free_cdi_device_node(dn);
+ free_defs_device(dev);
+ return -1;
+}
+
+static int defs_mount_parts(defs_mount *m)
+{
+ char cleanpath[PATH_MAX] = { 0 };
+ if (util_clean_path(m->destination, cleanpath, sizeof(cleanpath)) == NULL) {
+ return -1;
+ }
+
+ return util_strings_count(cleanpath, '/');
+}
+
+static inline int defs_mount_cmp(defs_mount **first, defs_mount **second)
+{
+ int first_part = defs_mount_parts(*first);
+ int second_part = defs_mount_parts(*second);
+
+ if (first_part < second_part) {
+ return -1;
+ }
+ if (first_part > second_part) {
+ return 1;
+ }
+
+ return strcmp((*first)->destination, (*second)->destination);
+}
+
+static int apply_cdi_mounts(cdi_container_edits *e, oci_runtime_spec *spec)
+{
+ size_t i;
+ defs_mount *mnt = NULL;
+
+ if (e->mounts_len == 0) {
+ return 0;
+ }
+
+ for (i = 0; i < e->mounts_len; i++) {
+ spec_remove_mount(spec, e->mounts[i]->container_path);
+ mnt = cdi_mount_to_oci(e->mounts[i]);
+ if (spec_add_mount(spec, mnt) != 0) {
+ free_defs_mount(mnt);
+ return -1;
+ }
+ }
+
+ qsort(spec->mounts, spec->mounts_len,
+ sizeof(defs_mount *), (int (*)(const void *, const void *))defs_mount_cmp);
+ return 0;
+}
+
+static int apply_cdi_hooks(cdi_container_edits *e, oci_runtime_spec *spec)
+{
+ size_t i;
+ int ret = 0;
+
+ for (i = 0; i < e->hooks_len; i++) {
+ defs_hook *oci_hook = cdi_hook_to_oci(e->hooks[i]);
+ if (strcmp(e->hooks[i]->hook_name, PRESTART_HOOK)) {
+ ret = spec_add_prestart_hook(spec, oci_hook);
+ } else if (strcmp(e->hooks[i]->hook_name, POSTSTART_HOOK)) {
+ ret = spec_add_poststart_hook(spec, oci_hook);
+ } else if (strcmp(e->hooks[i]->hook_name, POSTSTOP_HOOK)) {
+ ret = spec_add_poststop_hook(spec, oci_hook);
+ } else {
+ /*
+ * The OCI being used by the iSulad not supportes
+ * createRuntime/createContainer/startContainer currently.
+ */
+ ERROR("Unknown hook name %s", e->hooks[i]->hook_name);
+ free_defs_hook(oci_hook);
+ return -1;
+ }
+ if (ret != 0) {
+ ERROR("Failed add hook %s", e->hooks[i]->hook_name);
+ free_defs_hook(oci_hook);
+ return -1;
+ }
+ }
+ return ret;
+}
+
int cdi_container_edits_apply(cdi_container_edits *e, oci_runtime_spec *spec)
{
+ if (spec == NULL) {
+ ERROR("Can't edit nil OCI Spec");
+ return -1;
+ }
+ if (e == NULL) {
+ WARN("Cdi container edits is nil");
+ return 0;
+ }
+
+ if (e->env_len > 0) {
+ if (spec_add_multiple_process_env(spec, (const char **)e->env, e->env_len) != 0) {
+ ERROR("Failed to merge envs");
+ return -1;
+ }
+ }
+
+ if (apply_cdi_device_nodes(e, spec) != 0) {
+ ERROR("Failed to apply device nodes");
+ return -1;
+ }
+
+ if (apply_cdi_mounts(e, spec) != 0) {
+ ERROR("Failed to apply mounts");
+ return -1;
+ }
+
+ if (apply_cdi_hooks(e, spec) != 0) {
+ ERROR("Failed to apply hooks");
+ return -1;
+ }
+
return 0;
}
-int cdi_container_edits_validate(cdi_container_edits *e, char **error)
+int cdi_container_edits_validate(cdi_container_edits *e)
{
+ size_t i;
+
+ if (e == NULL) {
+ WARN("Cdi container edits is nil");
+ return 0;
+ }
+
+ if (cdi_validate_env(e->env, e->env_len) != 0) {
+ ERROR("Invalid container edits");
+ return -1;
+ }
+ for (i = 0; i < e->device_nodes_len; i++) {
+ if (cdi_validate_device_node(e->device_nodes[i]) != 0) {
+ ERROR("Invalid container device node");
+ return -1;
+ }
+ }
+ for (i = 0; i < e->hooks_len; i++) {
+ if (cdi_validate_hook(e->hooks[i]) != 0) {
+ ERROR("Invalid container hook");
+ return -1;
+ }
+ }
+ for (i = 0; i < e->mounts_len; i++) {
+ if (cdi_validate_mount(e->mounts[i]) != 0) {
+ ERROR("Invalid container mount");
+ return -1;
+ }
+ }
+
return 0;
}
+#define EDITS_APPEND_ITEM_DEF(item) \
+ static int append_##item(cdi_container_edits *e, cdi_container_edits *o, clone_common_array_item_cb cb) \
+ { \
+ common_array e_array = { \
+ .items = (void **)e->item, \
+ .len = e->item##_len, \
+ .cap = e->item##_len, \
+ .free_item_cb = NULL, \
+ .clone_item_cb = cb \
+ }; \
+ common_array o_array = { \
+ .items = (void **)o->item, \
+ .len = o->item##_len, \
+ .cap = o->item##_len, \
+ .free_item_cb = NULL, \
+ .clone_item_cb = cb \
+ }; \
+ if (util_merge_common_array(&e_array, &o_array) != 0) { \
+ ERROR("Out of memory"); \
+ return -1; \
+ } \
+ e->item = (void *)e_array.items; \
+ e->item##_len += o->item##_len; \
+ return 0; \
+ }
+
+EDITS_APPEND_ITEM_DEF(env)
+EDITS_APPEND_ITEM_DEF(device_nodes)
+EDITS_APPEND_ITEM_DEF(hooks)
+EDITS_APPEND_ITEM_DEF(mounts)
+
int cdi_container_edits_append(cdi_container_edits *e, cdi_container_edits *o)
{
+ if (o == NULL) {
+ return 0;
+ }
+ if (e == NULL) {
+ ERROR("Invalid params");
+ return -1;
+ }
+
+ if (append_env(e, o, (clone_common_array_item_cb)util_strdup_s) != 0) {
+ return -1;
+ }
+ if (append_device_nodes(e, o, (clone_common_array_item_cb)clone_cdi_device_node) != 0) {
+ return -1;
+ }
+ if (append_hooks(e, o, (clone_common_array_item_cb)clone_cdi_hook) != 0) {
+ return -1;
+ }
+ if (append_mounts(e, o, (clone_common_array_item_cb)clone_cdi_mount) != 0) {
+ return -1;
+ }
+
return 0;
}
bool cdi_container_edits_is_empty(cdi_container_edits *e)
{
- return true;
+ if (e == NULL) {
+ return false;
+ }
+ return e->env_len + e->device_nodes_len + e->hooks_len + e->mounts_len == 0;
}
+static int cdi_validate_env(char **envs, size_t envs_len)
+{
+ size_t i;
+ char *ptr = NULL;
+
+ for (i = 0; i < envs_len; i++) {
+ ptr = strchr(envs[i], '=');
+ if (ptr == NULL || ptr == envs[i]) {
+ ERROR("Invalid environment variable %s", envs[i]);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int cdi_validate_device_node(cdi_device_node *d)
+{
+ char *p = NULL;
+
+ if (d == NULL) {
+ ERROR("Device node is nil");
+ return -1;
+ }
+
+ if (d->path == NULL) {
+ ERROR("Invalid (empty) device path");
+ return -1;
+ }
+ if (d->type != NULL && strcmp(d->type, BLOCK_DEVICE) != 0 &&
+ strcmp(d->type, CHAR_DEVICE) != 0 && strcmp(d->type, FIFO_DEVICE) != 0) {
+ ERROR("Device %s: invalid type %s", d->path, d->type);
+ return -1;
+ }
+ for (p = d->permissions; p != NULL && *p != '\0'; p++) {
+ if (*p != 'r' && *p != 'w' && *p != 'm') {
+ ERROR("Device %s: invalid permissions %s", d->path, d->permissions);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int cdi_validate_hook(cdi_hook *h)
+{
+ size_t i;
+
+ if (h == NULL) {
+ ERROR("Hook is nil");
+ return -1;
+ }
+
+ for (i = 0; i < VALID_HOOK_NAME_LEN; i++) {
+ if (strcmp(h->hook_name, g_valid_hook_names[i]) == 0) {
+ break;
+ }
+ }
+ if (i == VALID_HOOK_NAME_LEN) {
+ ERROR("Invalid hook name %s", h->hook_name);
+ return -1;
+ }
+ if (h->path == NULL) {
+ ERROR("Invalid hook %s with empty path", h->hook_name);
+ return -1;
+ }
+ if (cdi_validate_env(h->env, h->env_len) != 0) {
+ ERROR("Invalid hook %s", h->hook_name);
+ return -1;
+ }
+ return 0;
+}
+
+static int cdi_validate_mount(cdi_mount *m)
+{
+ if (m == NULL) {
+ ERROR("Mount is nil");
+ return -1;
+ }
+
+ if (m->host_path == NULL) {
+ ERROR("Invalid mount, empty host path");
+ return -1;
+ }
+ if (m->container_path == NULL) {
+ ERROR("Invalid mount, empty container path");
+ return -1;
+ }
+ return 0;
+}
diff --git a/src/daemon/modules/device/cdi/behavior/cdi_container_edits.h b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.h
index ea921e37..ddceec25 100644
--- a/src/daemon/modules/device/cdi/behavior/cdi_container_edits.h
+++ b/src/daemon/modules/device/cdi/behavior/cdi_container_edits.h
@@ -28,7 +28,7 @@ extern "C" {
#endif
int cdi_container_edits_apply(cdi_container_edits *e, oci_runtime_spec *spec);
-int cdi_container_edits_validate(cdi_container_edits *e, char **error);
+int cdi_container_edits_validate(cdi_container_edits *e);
int cdi_container_edits_append(cdi_container_edits *e, cdi_container_edits *o);
bool cdi_container_edits_is_empty(cdi_container_edits *e);
diff --git a/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c
index 14293c72..8824d29c 100644
--- a/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c
+++ b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.c
@@ -14,42 +14,228 @@
******************************************************************************/
#include "cdi_parser.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <isula_libutils/log.h>
+#include <isula_libutils/auto_cleanup.h>
+
+#include "error.h"
+#include "utils_string.h"
+
+/* cdi_parser_qualified_name returns the qualified name for a device.
+ * The syntax for a qualified device names is
+ *
+ * "<vendor>/<class>=<name>".
+ *
+ * A valid vendor and class name may contain the following runes:
+ *
+ * 'A'-'Z', 'a'-'z', '0'-'9', '.', '-', '_'.
+ *
+ * A valid device name may contain the following runes:
+ *
+ * 'A'-'Z', 'a'-'z', '0'-'9', '-', '_', '.', ':'
+ */
char *cdi_parser_qualified_name(const char *vendor, const char *class, const char *name)
{
- return NULL;
+ char device_name[PATH_MAX] = { 0 };
+ int nret;
+
+ if (vendor == NULL || class == NULL || name == NULL) {
+ ERROR("Invalid argument");
+ return NULL;
+ }
+
+ nret = snprintf(device_name, sizeof(device_name), "%s/%s=%s",
+ vendor, class, name);
+ if (nret < 0 || (size_t)nret >= sizeof(device_name)) {
+ ERROR("Device name is too long");
+ return NULL;
+ }
+ return util_strdup_s(device_name);
}
+// cdi_parser_is_qualified_name tests if a device name is qualified.
bool cdi_parser_is_qualified_name(const char *device)
{
- return true;
+ __isula_auto_free char *vendor = NULL;
+ __isula_auto_free char *class = NULL;
+ __isula_auto_free char *name = NULL;
+
+ return cdi_parser_parse_qualified_name(device, &vendor, &class, &name) == 0;
}
+// cdi_parser_parse_qualified_name splits a qualified name into device vendor, class, and name.
int cdi_parser_parse_qualified_name(const char *device, char **vendor, char **class, char **name)
{
+ int ret = 0;
+
+ ret = cdi_parser_parse_device(device, vendor, class, name);
+ if (ret != 0) {
+ if (*vendor == NULL) {
+ ERROR("Unqualified device %s, missing vendor", device);
+ return -1;
+ }
+ if (*class == NULL) {
+ ERROR("Unqualified device %s, missing class", device);
+ return -1;
+ }
+ if (*name == NULL) {
+ ERROR("Unqualified device %s, missing name", device);
+ return -1;
+ }
+ ERROR("Unqualified device %s", device);
+ return -1;
+ }
+
+ if (cdi_parser_validate_vendor_name(*vendor) != 0) {
+ ERROR("Invalid device %s", device);
+ goto err_out;
+ }
+ if (cdi_parser_validate_class_name(*class) != 0) {
+ ERROR("Invalid device %s", device);
+ goto err_out;
+ }
+ if (cdi_parser_validate_device_name(*name) != 0) {
+ ERROR("Invalid device %s", device);
+ goto err_out;
+ }
+
return 0;
+
+err_out:
+ free(*vendor);
+ *vendor = NULL;
+ free(*class);
+ *class = NULL;
+ free(*name);
+ *name = NULL;
+ return -1;
}
+// cdi_parser_parse_device tries to split a device name into vendor, class, and name.
int cdi_parser_parse_device(const char *device, char **vendor, char **class, char **name)
{
+ __isula_auto_array_t char **parts = NULL;
+
+ if (vendor == NULL || class == NULL || name == NULL ||
+ device == NULL || device[0] == '/') {
+ ERROR("Invalid argument");
+ return -1;
+ }
+
+ parts = util_string_split_n(device, '=', 2);
+ if (parts == NULL || util_array_len((const char **)parts) != 2 || parts[0] == NULL || parts[1] == NULL) {
+ return -1;
+ }
+
+ *name = parts[1];
+ parts[1] = NULL;
+ (void)cdi_parser_parse_qualifier(parts[0], vendor, class);
+ if (*vendor == NULL) {
+ ERROR("Failed to parse device qualifier: %s", parts[0]);
+ return -1;
+ }
+
return 0;
}
+/* cdi_parser_parse_qualifier splits a device qualifier into vendor and class.
+ * The syntax for a device qualifier is
+ *
+ * "<vendor>/<class>"
+ */
int cdi_parser_parse_qualifier(const char *kind, char **vendor, char **class)
{
+ __isula_auto_array_t char **parts = NULL;
+
+ if (kind == NULL || vendor == NULL || class == NULL) {
+ ERROR("Invalid argument");
+ return -1;
+ }
+
+ parts = util_string_split_n(kind, '/', 2);
+ if (parts == NULL || util_array_len((const char **)parts) != 2 || parts[0] == NULL || parts[1] == NULL) {
+ return -1;
+ }
+ *vendor = parts[0];
+ parts[0] = NULL;
+ *class = parts[1];
+ parts[1] = NULL;
+
+ return 0;
+}
+
+static int validate_vendor_or_class_name(const char *name)
+{
+ int i = 0;
+
+ if (name == NULL) {
+ ERROR("Empty name");
+ return -1;
+ }
+
+ if (!isalpha(name[0])) {
+ ERROR("%s, should start with letter", name);
+ return -1;
+ }
+ for (i = 1; name[i] != '\0'; i++) {
+ if (!(isalnum(name[i]) || name[i] == '_' || name[i] == '-' || name[i] == '.')) {
+ ERROR("Invalid character '%c' in name %s", name[i], name);
+ return -1;
+ }
+ }
+ if (!isalnum(name[i - 1])) {
+ ERROR("%s, should end with a letter or digit", name);
+ return -1;
+ }
+
return 0;
}
-int cdi_parser_validate_vendor_name(const char *vendor, char **error)
+int cdi_parser_validate_vendor_name(const char *vendor)
{
+ if (validate_vendor_or_class_name(vendor) != 0) {
+ ERROR("Invalid vendor");
+ return -1;
+ }
return 0;
}
-int cdi_parser_validate_class_name(const char *class, char **error)
+int cdi_parser_validate_class_name(const char *class)
{
+ if (validate_vendor_or_class_name(class) != 0) {
+ ERROR("Invalid class.");
+ return -1;
+ }
return 0;
}
-int cdi_parser_validate_device_name(const char *name, char **error)
+int cdi_parser_validate_device_name(const char *name)
{
+ size_t i;
+
+ if (name == NULL) {
+ ERROR("Invalid (empty) device name");
+ return -1;
+ }
+ if (!isalnum(name[0])) {
+ ERROR("Invalid class %s, should start with a letter or digit", name);
+ return -1;
+ }
+ if (strlen(name) == 1) {
+ return 0;
+ }
+ for (i = 1; name[i] != '\0'; i++) {
+ if (!(isalnum(name[i]) || name[i] == '_' || name[i] == '-' || name[i] == '.' || name[i] == ':')) {
+ ERROR("Invalid character '%c' in device name %s", name[i], name);
+ return -1;
+ }
+ }
+ if (!isalnum(name[i - 1])) {
+ ERROR("Invalid name %s, should end with a letter or digit", name);
+ return -1;
+ }
+
return 0;
}
diff --git a/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h
index 467641a1..3658e29b 100644
--- a/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h
+++ b/src/daemon/modules/device/cdi/behavior/parser/cdi_parser.h
@@ -27,9 +27,9 @@ bool cdi_parser_is_qualified_name(const char *device);
int cdi_parser_parse_qualified_name(const char *device, char **vendor, char **class, char **name);
int cdi_parser_parse_device(const char *device, char **vendor, char **class, char **name);
int cdi_parser_parse_qualifier(const char *kind, char **vendor, char **class);
-int cdi_parser_validate_vendor_name(const char *vendor, char **error);
-int cdi_parser_validate_class_name(const char *class, char **error);
-int cdi_parser_validate_device_name(const char *name, char **error);
+int cdi_parser_validate_vendor_name(const char *vendor);
+int cdi_parser_validate_class_name(const char *class);
+int cdi_parser_validate_device_name(const char *name);
#ifdef __cplusplus
}
diff --git a/src/daemon/modules/spec/specs.c b/src/daemon/modules/spec/specs.c
index b4d2b0f6..77ca70f9 100644
--- a/src/daemon/modules/spec/specs.c
+++ b/src/daemon/modules/spec/specs.c
@@ -29,6 +29,7 @@
#include <isula_libutils/host_config.h>
#include <isula_libutils/log.h>
#include <isula_libutils/auto_cleanup.h>
+#include <isula_libutils/utils_array.h>
#include "specs_api.h"
#include "utils.h"
@@ -2595,3 +2596,232 @@ int spec_module_init(void)
return 0;
}
+#ifdef ENABLE_CDI
+static int add_env(defs_process *dp, const char *env, const char *key)
+{
+ size_t i;
+ char *oci_key = NULL;
+ char *oci_value = NULL;
+ char *saveptr = NULL;
+ __isula_auto_free char *tmp_env = NULL;
+
+ for (i = 0; i < dp->env_len; i++) {
+ tmp_env = util_strdup_s(dp->env[i]);
+ oci_key = strtok_r(tmp_env, "=", &saveptr);
+ oci_value = strtok_r(NULL, "=", &saveptr);
+ if (oci_key == NULL || oci_value == NULL) {
+ ERROR("Bad env format");
+ return -1;
+ }
+ if (strcmp(key, oci_key) == 0) {
+ free(dp->env[i]);
+ dp->env[i] = util_strdup_s(env);
+ return 0;
+ }
+ free(tmp_env);
+ tmp_env = NULL;
+ }
+ if (util_mem_realloc((void **)&dp->env, (dp->env_len + 1) * sizeof(char *),
+ (void *)dp->env, dp->env_len * sizeof(char *)) != 0) {
+ ERROR("Out of memory");
+ return -1;
+ }
+ dp->env[dp->env_len] = util_strdup_s(env);
+ dp->env_len++;
+ return 0;
+}
+
+int defs_process_add_multiple_env(defs_process *dp, const char **envs, size_t env_len)
+{
+ size_t i;
+ char *key = NULL;
+ char *value = NULL;
+ char *saveptr = NULL;
+ __isula_auto_free char *tmp_env = NULL;
+
+ if (envs == NULL || env_len == 0) {
+ DEBUG("empty envs");
+ return 0;
+ }
+ if (dp == NULL) {
+ ERROR("Invalid params");
+ return -1;
+ }
+
+ for (i = 0; i < env_len; i++) {
+ tmp_env = util_strdup_s(envs[i]);
+ key = strtok_r(tmp_env, "=", &saveptr);
+ value = strtok_r(NULL, "=", &saveptr);
+ if (key == NULL || value == NULL) {
+ ERROR("Bad env format: %s", tmp_env);
+ return -1;
+ }
+ if (add_env(dp, envs[i], key) != 0) {
+ return -1;
+ }
+ free(tmp_env);
+ tmp_env = NULL;
+ }
+
+ return 0;
+}
+
+int spec_add_multiple_process_env(oci_runtime_spec *oci_spec, const char **envs, size_t env_len)
+{
+ int ret = 0;
+
+ if (envs == NULL || env_len == 0) {
+ DEBUG("empty envs");
+ return 0;
+ }
+ if (oci_spec == NULL) {
+ ERROR("Invalid params");
+ return -1;
+ }
+
+ ret = make_sure_oci_spec_process(oci_spec);
+ if (ret < 0) {
+ ERROR("Out of memory");
+ return -1;
+ }
+
+ ret = defs_process_add_multiple_env(oci_spec->process, envs, env_len);
+ if (ret < 0) {
+ ERROR("Failed to add envs");
+ }
+
+ return ret;
+}
+
+int spec_add_device(oci_runtime_spec *oci_spec, defs_device *device)
+{
+ int ret = 0;
+ size_t i;
+
+ if (device == NULL) {
+ return -1;
+ }
+ ret = make_sure_oci_spec_linux(oci_spec);
+ if (ret < 0) {
+ return -1;
+ }
+
+ for (i = 0; i < oci_spec->linux->devices_len; i++) {
+ if (strcmp(oci_spec->linux->devices[i]->path, device->path) == 0) {
+ free_defs_device(oci_spec->linux->devices[i]);
+ oci_spec->linux->devices[i] = device;
+ return 0;
+ }
+ }
+
+ if (util_mem_realloc((void **)&oci_spec->linux->devices, (oci_spec->linux->devices_len + 1) * sizeof(char *),
+ (void *)oci_spec->linux->devices, oci_spec->linux->devices_len * sizeof(char *)) != 0) {
+ ERROR("Out of memory");
+ return -1;
+ }
+ oci_spec->linux->devices[oci_spec->linux->devices_len] = device;
+ oci_spec->linux->devices_len++;
+
+ return 0;
+}
+
+int spec_add_linux_resources_device(oci_runtime_spec *oci_spec, bool allow, const char *dev_type,
+ int64_t major, int64_t minor, const char *access)
+{
+ int ret = 0;
+ defs_device_cgroup *device = NULL;
+
+ ret = make_sure_oci_spec_linux_resources(oci_spec);
+ if (ret < 0) {
+ return -1;
+ }
+
+ device = util_common_calloc_s(sizeof(*device));
+ if (device == NULL) {
+ ERROR("Out of memory");
+ return -1;
+ }
+ device->allow = allow;
+ device->type = util_strdup_s(dev_type);
+ device->access = util_strdup_s(access);
+ device->major = major;
+ device->minor = minor;
+
+ if (util_mem_realloc((void **)&oci_spec->linux->resources->devices, (oci_spec->linux->resources->devices_len + 1) * sizeof(char *),
+ (void *)oci_spec->linux->resources->devices, oci_spec->linux->resources->devices_len * sizeof(char *)) != 0) {
+ ERROR("Out of memory");
+ free_defs_device_cgroup(device);
+ return -1;
+ }
+ oci_spec->linux->resources->devices[oci_spec->linux->resources->devices_len] = device;
+ oci_spec->linux->resources->devices_len++;
+
+ return 0;
+}
+
+void spec_remove_mount(oci_runtime_spec *oci_spec, const char *dest)
+{
+ size_t i;
+
+ if (oci_spec == NULL || oci_spec->mounts == NULL || dest == NULL) {
+ return;
+ }
+
+ for (i = 0; i < oci_spec->mounts_len; i++) {
+ if (strcmp(oci_spec->mounts[i]->destination, dest) == 0) {
+ free_defs_mount(oci_spec->mounts[i]);
+ (void)memcpy((void **)&oci_spec->mounts[i], (void **)&oci_spec->mounts[i + 1],
+ (oci_spec->mounts_len - i - 1) * sizeof(void *));
+ oci_spec->mounts_len--;
+ return;
+ }
+ }
+}
+
+int spec_add_mount(oci_runtime_spec *oci_spec, defs_mount *mnt)
+{
+ if (oci_spec == NULL || mnt == NULL) {
+ return -1;
+ }
+
+ if (util_mem_realloc((void **)&oci_spec->mounts, (oci_spec->mounts_len + 1) * sizeof(char *),
+ (void *)oci_spec->mounts, oci_spec->mounts_len * sizeof(char *)) != 0) {
+ ERROR("Out of memory");
+ return -1;
+ }
+ oci_spec->mounts[oci_spec->mounts_len] = mnt;
+ oci_spec->mounts_len++;
+
+ return 0;
+}
+
+#define SPEC_ADD_HOOKS_ITEM_DEF(hooktype) \
+ int spec_add_##hooktype##_hook(oci_runtime_spec *oci_spec, defs_hook *hooktype##_hook) \
+ { \
+ int ret = 0; \
+ if (oci_spec == NULL || hooktype##_hook == NULL) { \
+ return -1; \
+ } \
+ ret = make_sure_oci_spec_hooks(oci_spec); \
+ if (ret < 0) { \
+ return -1; \
+ } \
+ if (util_mem_realloc((void **)&oci_spec->hooks->hooktype, (oci_spec->hooks->hooktype##_len + 1) * sizeof(char *), \
+ (void *)oci_spec->hooks->hooktype, oci_spec->hooks->hooktype##_len * sizeof(char *)) != 0) { \
+ ERROR("Out of memory"); \
+ return -1; \
+ } \
+ oci_spec->hooks->hooktype[oci_spec->hooks->hooktype##_len] = hooktype##_hook; \
+ oci_spec->hooks->hooktype##_len++; \
+ return 0; \
+ }
+
+/*
+* The OCI being used by the iSulad not supportes
+* createRuntime/createContainer/startContainer currently.
+*/
+SPEC_ADD_HOOKS_ITEM_DEF(prestart)
+SPEC_ADD_HOOKS_ITEM_DEF(poststart)
+SPEC_ADD_HOOKS_ITEM_DEF(poststop)
+
+#endif /* ENABLE_CDI */
\ No newline at end of file
--
2.34.1

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/src-openeuler-iSulad.git
git@api.gitlife.ru:oschina-mirror/src-openeuler-iSulad.git
oschina-mirror
src-openeuler-iSulad
src-openeuler-iSulad
master