483 lines
17 KiB
Diff
483 lines
17 KiB
Diff
From 7a2dd92a527c1f5ee79239d93b792dc9a9758e27 Mon Sep 17 00:00:00 2001
|
|
From: liuxu <liuxu156@huawei.com>
|
|
Date: Tue, 7 Nov 2023 20:38:22 +0800
|
|
Subject: [PATCH 04/14] network:support version opt
|
|
|
|
---
|
|
.../network/cni_operator/cni_operate.c | 16 +++
|
|
.../network/cni_operator/cni_operate.h | 3 +
|
|
.../cni_operator/libcni/invoke/libcni_exec.c | 86 +++++++++++++-
|
|
.../cni_operator/libcni/invoke/libcni_exec.h | 2 +
|
|
.../libcni/invoke/libcni_result_parse.c | 29 +++++
|
|
.../libcni/invoke/libcni_result_parse.h | 6 +
|
|
.../network/cni_operator/libcni/libcni_api.c | 106 ++++++++++++++++++
|
|
.../network/cni_operator/libcni/libcni_api.h | 8 +-
|
|
.../cni_operator/libcni/libcni_result_type.c | 18 +++
|
|
.../cni_operator/libcni/libcni_result_type.h | 12 ++
|
|
.../modules/network/native/adaptor_native.c | 3 +-
|
|
11 files changed, 281 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/src/daemon/modules/network/cni_operator/cni_operate.c b/src/daemon/modules/network/cni_operator/cni_operate.c
|
|
index 62249f18..6db6db51 100644
|
|
--- a/src/daemon/modules/network/cni_operator/cni_operate.c
|
|
+++ b/src/daemon/modules/network/cni_operator/cni_operate.c
|
|
@@ -926,6 +926,22 @@ out:
|
|
return ret;
|
|
}
|
|
|
|
+int version_network_plane(const struct cni_network_list_conf *list,
|
|
+ struct cni_version_info_list **result_version_list)
|
|
+{
|
|
+ if (list == NULL || list->list == NULL) {
|
|
+ ERROR("Invalid input params");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (cni_version_network_list(list, result_version_list) != 0) {
|
|
+ ERROR("Version CNI network failed");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
int detach_loopback(const char *id, const char *netns)
|
|
{
|
|
int ret = 0;
|
|
diff --git a/src/daemon/modules/network/cni_operator/cni_operate.h b/src/daemon/modules/network/cni_operator/cni_operate.h
|
|
index 150c1154..7750ff00 100644
|
|
--- a/src/daemon/modules/network/cni_operator/cni_operate.h
|
|
+++ b/src/daemon/modules/network/cni_operator/cni_operate.h
|
|
@@ -61,6 +61,9 @@ int detach_network_plane(const struct cni_manager *manager, const struct cni_net
|
|
int check_network_plane(const struct cni_manager *manager, const struct cni_network_list_conf *list,
|
|
struct cni_opt_result **result);
|
|
|
|
+int version_network_plane(const struct cni_network_list_conf *list,
|
|
+ struct cni_version_info_list **result_version_list);
|
|
+
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
diff --git a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c
|
|
index c4bc81c0..4908565e 100644
|
|
--- a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c
|
|
+++ b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.c
|
|
@@ -28,7 +28,7 @@
|
|
#include <sys/wait.h>
|
|
|
|
#include <isula_libutils/cni_inner_plugin_info.h>
|
|
-#include <isula_libutils/cni_version.h>
|
|
+#include <isula_libutils/cni_version_info.h>
|
|
#include <isula_libutils/log.h>
|
|
#include <isula_libutils/cni_exec_error.h>
|
|
#include <isula_libutils/auto_cleanup.h>
|
|
@@ -183,10 +183,10 @@ static char *str_cni_exec_error(const cni_exec_error *e_err)
|
|
static char *cniversion_decode(const char *jsonstr)
|
|
{
|
|
__isula_auto_free parser_error err = NULL;
|
|
- cni_version *conf = NULL;
|
|
+ cni_version_info *conf = NULL;
|
|
char *result = NULL;
|
|
|
|
- conf = cni_version_parse_data(jsonstr, NULL, &err);
|
|
+ conf = cni_version_info_parse_data(jsonstr, NULL, &err);
|
|
if (conf == NULL) {
|
|
ERROR("decoding config \"%s\", failed: %s", jsonstr, err);
|
|
goto out;
|
|
@@ -198,7 +198,7 @@ static char *cniversion_decode(const char *jsonstr)
|
|
|
|
result = util_strdup_s(conf->cni_version);
|
|
out:
|
|
- free_cni_version(conf);
|
|
+ free_cni_version_info(conf);
|
|
return result;
|
|
}
|
|
|
|
@@ -466,6 +466,84 @@ out:
|
|
return ret;
|
|
}
|
|
|
|
+static char *get_default_version_stdin(void)
|
|
+{
|
|
+ char *stdin_str = NULL;
|
|
+ int ret;
|
|
+
|
|
+ ret = asprintf(&stdin_str, "{\"cniVersion\":\"%s\"}", CURRENT_VERSION);
|
|
+ if (ret < 0) {
|
|
+ ERROR("parse cni version failed");
|
|
+ }
|
|
+ return stdin_str;
|
|
+}
|
|
+
|
|
+static int do_parse_version_info_stdout_str(int exec_ret, const cni_exec_error *e_err,
|
|
+ const char *stdout_str, cni_version_info **result_version)
|
|
+{
|
|
+ __isula_auto_free char *err_msg = NULL;
|
|
+ struct parser_context ctx = { OPT_GEN_SIMPLIFY, 0 };
|
|
+ __isula_auto_free parser_error perr = NULL;
|
|
+
|
|
+ if (exec_ret != 0) {
|
|
+ err_msg = str_cni_exec_error(e_err);
|
|
+ ERROR("raw exec failed: %s", err_msg);
|
|
+ isulad_append_error_message("raw exec failed: %s. ", err_msg);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (stdout_str == NULL || strlen(stdout_str) == 0) {
|
|
+ ERROR("Get empty version result");
|
|
+ return -1;
|
|
+ }
|
|
+ free_cni_version_info(*result_version);
|
|
+ *result_version = cni_version_info_parse_data(stdout_str, &ctx, &perr);
|
|
+ if (*result_version == NULL) {
|
|
+ ERROR("parse cni result version failed: %s", perr);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int get_version_info(const char *plugin_path, cni_version_info **result_version)
|
|
+{
|
|
+ __isula_auto_free char *err_msg = NULL;
|
|
+ char **envs = NULL;
|
|
+ __isula_auto_free char *stdout_str = NULL;
|
|
+ __isula_auto_free char *stdin_str = NULL;
|
|
+ cni_exec_error *e_err = NULL;
|
|
+ int ret = 0;
|
|
+ const struct cni_args cniargs = {
|
|
+ .command = "VERSION",
|
|
+ .netns = "dummy",
|
|
+ .ifname = "dummy",
|
|
+ .path = "dummy",
|
|
+ .container_id = "dummy"
|
|
+ };
|
|
+
|
|
+ stdin_str = get_default_version_stdin();
|
|
+ if (stdin_str == NULL) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ envs = as_env(&cniargs);
|
|
+ if (envs == NULL) {
|
|
+ ERROR("create env failed");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ ret = raw_exec(plugin_path, stdin_str, envs, &stdout_str, &e_err);
|
|
+ DEBUG("Raw exec \"%s\" result: %d", plugin_path, ret);
|
|
+ DEBUG("Raw exec stdout: %s", stdout_str);
|
|
+ ret = do_parse_version_info_stdout_str(ret, e_err, stdout_str, result_version);
|
|
+
|
|
+ util_free_array(envs);
|
|
+ free_cni_exec_error(e_err);
|
|
+ return ret;
|
|
+
|
|
+}
|
|
+
|
|
void free_cni_args(struct cni_args *cargs)
|
|
{
|
|
size_t i = 0;
|
|
diff --git a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.h b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.h
|
|
index 60b1c972..48d8d8b6 100644
|
|
--- a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.h
|
|
+++ b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_exec.h
|
|
@@ -40,6 +40,8 @@ int exec_plugin_with_result(const char *plugin_path, const char *cni_net_conf_js
|
|
|
|
int exec_plugin_without_result(const char *plugin_path, const char *cni_net_conf_json, const struct cni_args *cniargs);
|
|
|
|
+int get_version_info(const char *plugin_path, cni_version_info **result_version);
|
|
+
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
diff --git a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.c b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.c
|
|
index 164b2e29..aa4f75cf 100644
|
|
--- a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.c
|
|
+++ b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.c
|
|
@@ -741,3 +741,32 @@ struct cni_opt_result *new_result(const char *version, const char *jsonstr)
|
|
ERROR("unsupported CNI result version \"%s\"", version);
|
|
return NULL;
|
|
}
|
|
+
|
|
+size_t get_curr_support_version_len(void)
|
|
+{
|
|
+ return CURR_SUPPORT_VERSION_LEN;
|
|
+}
|
|
+
|
|
+int get_support_version_pos(const char *version)
|
|
+{
|
|
+ int i = 0;
|
|
+ if (version == NULL) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ for (i = CURR_SUPPORT_VERSION_LEN - 1; i >= 0; i--) {
|
|
+ if ((g_curr_support_versions[i] != NULL) && (strcmp(version, g_curr_support_versions[i]) == 0)) {
|
|
+ return i;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+const char *get_support_version_by_pos(size_t pos)
|
|
+{
|
|
+ if (pos >= CURR_SUPPORT_VERSION_LEN) {
|
|
+ return NULL;
|
|
+ }
|
|
+ return g_curr_support_versions[pos];
|
|
+}
|
|
\ No newline at end of file
|
|
diff --git a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.h b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.h
|
|
index 547bc915..438e1332 100644
|
|
--- a/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.h
|
|
+++ b/src/daemon/modules/network/cni_operator/libcni/invoke/libcni_result_parse.h
|
|
@@ -37,6 +37,12 @@ cni_result_curr *cni_result_curr_to_json_result(const struct cni_opt_result *src
|
|
|
|
struct cni_opt_result *copy_result_from_current(const cni_result_curr *curr_result);
|
|
|
|
+size_t get_curr_support_version_len(void);
|
|
+
|
|
+int get_support_version_pos(const char *version);
|
|
+
|
|
+const char *get_support_version_by_pos(size_t pos);
|
|
+
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
diff --git a/src/daemon/modules/network/cni_operator/libcni/libcni_api.c b/src/daemon/modules/network/cni_operator/libcni/libcni_api.c
|
|
index 781759e8..7f62df78 100644
|
|
--- a/src/daemon/modules/network/cni_operator/libcni/libcni_api.c
|
|
+++ b/src/daemon/modules/network/cni_operator/libcni/libcni_api.c
|
|
@@ -843,6 +843,112 @@ free_out:
|
|
return ret;
|
|
}
|
|
|
|
+static int version_network(const char *plugin_name, cni_version_info **result_version)
|
|
+{
|
|
+ int ret = 0;
|
|
+ __isula_auto_free char *plugin_path = NULL;
|
|
+
|
|
+ if (plugin_name == NULL) {
|
|
+ ERROR("Empty plugin name");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ ret = find_plugin_in_path(plugin_name, (const char * const *)g_module_conf.bin_paths,
|
|
+ g_module_conf.bin_paths_len, &plugin_path);
|
|
+ if (ret != 0) {
|
|
+ ERROR("Failed to find plugin: \"%s\"", plugin_name);
|
|
+ isulad_append_error_message("Failed to find plugin: \"%s\". ", plugin_name);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ // cni plugin calls should not take longer than 90 seconds
|
|
+ CALL_CHECK_TIMEOUT(90, ret = get_version_info(plugin_path, result_version));
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int cni_version_network_list(const struct cni_network_list_conf *list,
|
|
+ struct cni_version_info_list **result_version_list)
|
|
+{
|
|
+ int ret = 0;
|
|
+ int i;
|
|
+ cni_version_info *tmp_result_version = NULL;
|
|
+
|
|
+ if ((list == NULL) || (list->list == NULL) || (result_version_list == NULL)) {
|
|
+ ERROR("Empty arguments");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ *result_version_list = util_common_calloc_s(sizeof(struct cni_version_info_list));
|
|
+ if (*result_version_list == NULL) {
|
|
+ ERROR("Out of memory");
|
|
+ return -1;
|
|
+ }
|
|
+ (*result_version_list)->result_versions = util_smart_calloc_s(sizeof(cni_version_info *), list->list->plugins_len);
|
|
+ if ((*result_version_list)->result_versions == NULL) {
|
|
+ ERROR("Out of memory");
|
|
+ ret = -1;
|
|
+ goto free_out;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < list->list->plugins_len; i++) {
|
|
+ if (version_network(list->list->plugins[i]->type, &tmp_result_version) != 0) {
|
|
+ ret = -1;
|
|
+ ERROR("Run version plugin: %d failed", i);
|
|
+ goto free_out;
|
|
+ }
|
|
+ (*result_version_list)->result_versions[i] = tmp_result_version;
|
|
+ (*result_version_list)->result_versions_len += 1;
|
|
+ tmp_result_version = NULL;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+
|
|
+free_out:
|
|
+ free_cni_version_info_list(*result_version_list);
|
|
+ *result_version_list = NULL;
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+/* get the latest CNI version supported by all plugins */
|
|
+char *cni_get_plugins_supported_version(cni_net_conf_list *list)
|
|
+{
|
|
+ // init to default version, if no found, just return default version
|
|
+ char *cni_version = util_strdup_s(CURRENT_VERSION);
|
|
+ int i, j, version_pos;
|
|
+ struct cni_version_info_list *result_version_list = NULL;
|
|
+ struct cni_network_list_conf network_list = {
|
|
+ .list = list,
|
|
+ };
|
|
+ size_t curr_support_version_len = get_curr_support_version_len();
|
|
+ __isula_auto_free size_t *plugin_version_count = util_smart_calloc_s(sizeof(size_t), curr_support_version_len);
|
|
+ if (plugin_version_count == NULL) {
|
|
+ return cni_version;
|
|
+ }
|
|
+ if (cni_version_network_list(&network_list, &result_version_list) != 0) {
|
|
+ return cni_version;
|
|
+ }
|
|
+
|
|
+ // count plugin supported version
|
|
+ for (i = 0; i < result_version_list->result_versions_len; i++) {
|
|
+ for (j = result_version_list->result_versions[i]->supported_versions_len - 1; j >= 0 ; j--) {
|
|
+ version_pos = get_support_version_pos(result_version_list->result_versions[i]->supported_versions[j]);
|
|
+ if (version_pos < 0) {
|
|
+ break;
|
|
+ }
|
|
+ plugin_version_count[version_pos]++;
|
|
+ if (plugin_version_count[version_pos] == list->plugins_len) {
|
|
+ free(cni_version);
|
|
+ cni_version = util_strdup_s(get_support_version_by_pos(version_pos));
|
|
+ goto free_out;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+free_out:
|
|
+ free_cni_version_info_list(result_version_list);
|
|
+ return cni_version;
|
|
+}
|
|
+
|
|
static int do_copy_plugin_args(const struct runtime_conf *rc, struct cni_args **cargs)
|
|
{
|
|
size_t i = 0;
|
|
diff --git a/src/daemon/modules/network/cni_operator/libcni/libcni_api.h b/src/daemon/modules/network/cni_operator/libcni/libcni_api.h
|
|
index 878cb1bb..f94ab3f7 100644
|
|
--- a/src/daemon/modules/network/cni_operator/libcni/libcni_api.h
|
|
+++ b/src/daemon/modules/network/cni_operator/libcni/libcni_api.h
|
|
@@ -28,9 +28,6 @@
|
|
extern "C" {
|
|
#endif
|
|
|
|
-#define CURRENT_VERSION "1.0.0"
|
|
-#define SUPPORT_CACHE_AND_CHECK_VERSION "0.4.0"
|
|
-
|
|
#define SUPPORT_CAPABILITY_PORTMAPPINGS "portMappings"
|
|
#define SUPPORT_CAPABILITY_BANDWIDTH "bandwidth"
|
|
#define SUPPORT_CAPABILITY_IPRANGES "ipRanges"
|
|
@@ -87,6 +84,11 @@ int cni_del_network_list(const struct cni_network_list_conf *list, const struct
|
|
|
|
int cni_check_network_list(const struct cni_network_list_conf *list, const struct runtime_conf *rc,
|
|
struct cni_opt_result **p_result);
|
|
+
|
|
+int cni_version_network_list(const struct cni_network_list_conf *list,
|
|
+ struct cni_version_info_list **result_version_list);
|
|
+
|
|
+char *cni_get_plugins_supported_version(cni_net_conf_list *list);
|
|
|
|
void free_cni_port_mapping(struct cni_port_mapping *val);
|
|
|
|
diff --git a/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c b/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c
|
|
index fd1091de..8a0ce1dd 100644
|
|
--- a/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c
|
|
+++ b/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.c
|
|
@@ -129,3 +129,21 @@ void free_cni_opt_result(struct cni_opt_result *val)
|
|
val->my_dns = NULL;
|
|
free(val);
|
|
}
|
|
+
|
|
+void free_cni_version_info_list(struct cni_version_info_list *val)
|
|
+{
|
|
+ size_t i = 0;
|
|
+
|
|
+ if (val == NULL) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < val->result_versions_len; i++) {
|
|
+ free_cni_version_info(val->result_versions[i]);
|
|
+ val->result_versions[i] = NULL;
|
|
+ }
|
|
+ free(val->result_versions);
|
|
+ val->result_versions = NULL;
|
|
+
|
|
+ free(val);
|
|
+}
|
|
diff --git a/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.h b/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.h
|
|
index abbc22fe..36640e63 100644
|
|
--- a/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.h
|
|
+++ b/src/daemon/modules/network/cni_operator/libcni/libcni_result_type.h
|
|
@@ -19,10 +19,15 @@
|
|
#include <sys/types.h>
|
|
#include <stdbool.h>
|
|
|
|
+#include <isula_libutils/cni_version_info.h>
|
|
+
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
+#define CURRENT_VERSION "1.0.0"
|
|
+#define SUPPORT_CACHE_AND_CHECK_VERSION "0.4.0"
|
|
+
|
|
/* define types for version */
|
|
struct cni_opt_result_interface {
|
|
char *name;
|
|
@@ -73,6 +78,11 @@ struct cni_opt_result {
|
|
struct cni_opt_result_dns *my_dns;
|
|
};
|
|
|
|
+struct cni_version_info_list {
|
|
+ cni_version_info **result_versions;
|
|
+ size_t result_versions_len;
|
|
+};
|
|
+
|
|
void free_cni_opt_result_ipconfig(struct cni_opt_result_ipconfig *ipc);
|
|
|
|
void free_cni_opt_result_route(struct cni_opt_result_route *val);
|
|
@@ -83,6 +93,8 @@ void free_cni_opt_result_dns(struct cni_opt_result_dns *val);
|
|
|
|
void free_cni_opt_result(struct cni_opt_result *val);
|
|
|
|
+void free_cni_version_info_list(struct cni_version_info_list *val);
|
|
+
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
diff --git a/src/daemon/modules/network/native/adaptor_native.c b/src/daemon/modules/network/native/adaptor_native.c
|
|
index 4c63dec1..45288d7e 100644
|
|
--- a/src/daemon/modules/network/native/adaptor_native.c
|
|
+++ b/src/daemon/modules/network/native/adaptor_native.c
|
|
@@ -26,6 +26,7 @@
|
|
#include "linked_list.h"
|
|
#include "isulad_config.h"
|
|
#include <isula_libutils/log.h>
|
|
+#include <isula_libutils/auto_cleanup.h>
|
|
#include "utils_network.h"
|
|
#include "network_tools.h"
|
|
#include "cni_operate.h"
|
|
@@ -1301,7 +1302,7 @@ static cni_net_conf_list *conf_bridge(const network_create_request *request, str
|
|
list->plugins_len++;
|
|
}
|
|
|
|
- list->cni_version = util_strdup_s(CURRENT_VERSION);
|
|
+ list->cni_version = cni_get_plugins_supported_version(list);
|
|
if (request->name != NULL) {
|
|
list->name = util_strdup_s(request->name);
|
|
} else {
|
|
--
|
|
2.42.0
|
|
|