From 21bca2bb054ed7a1b9b78e01965f8a6d9c3fd28d Mon Sep 17 00:00:00 2001 From: zhongtao Date: Mon, 20 Nov 2023 12:58:26 +0000 Subject: [PATCH 19/64] !2254 lcr container with a damaged config file will rebuild the config during restore * lcr container with a damaged config file will rebuild the config during restore --- src/common/constants.h | 2 + src/daemon/modules/api/runtime_api.h | 7 ++ .../modules/container/restore/restore.c | 28 ++++-- .../modules/runtime/engines/lcr/lcr_rt_ops.c | 99 ++++++++++++++++++- .../modules/runtime/engines/lcr/lcr_rt_ops.h | 1 + .../modules/runtime/isula/isula_rt_ops.c | 6 ++ .../modules/runtime/isula/isula_rt_ops.h | 1 + src/daemon/modules/runtime/runtime.c | 24 +++++ src/daemon/modules/runtime/shim/shim_rt_ops.c | 6 ++ src/daemon/modules/runtime/shim/shim_rt_ops.h | 2 + 10 files changed, 167 insertions(+), 9 deletions(-) diff --git a/src/common/constants.h b/src/common/constants.h index caf9b793..5f12ae25 100644 --- a/src/common/constants.h +++ b/src/common/constants.h @@ -86,6 +86,8 @@ extern "C" { #define LOG_MAX_RETRIES 10 +#define INVALID_CONFIG_ERR_CODE 2 + #define MAX_MSG_BUFFER_SIZE (32 * 1024) #define DEFAULT_WEBSOCKET_SERVER_LISTENING_PORT 10350 diff --git a/src/daemon/modules/api/runtime_api.h b/src/daemon/modules/api/runtime_api.h index 3c2100f5..08558f42 100644 --- a/src/daemon/modules/api/runtime_api.h +++ b/src/daemon/modules/api/runtime_api.h @@ -41,6 +41,7 @@ typedef enum { struct runtime_container_status_info { bool has_pid; uint32_t pid; + int error_code; Runtime_Container_Status status; }; @@ -197,6 +198,10 @@ typedef struct _rt_exec_resize_params_t { unsigned int width; } rt_exec_resize_params_t; +typedef struct _rt_runtime_rebuild_config_params_t { + const char *rootpath; +} rt_rebuild_config_params_t; + struct rt_ops { /* detect whether runtime is of this runtime type */ bool (*detect)(const char *runtime); @@ -233,6 +238,7 @@ struct rt_ops { rt_listpids_out_t *out); int (*rt_resize)(const char *name, const char *runtime, const rt_resize_params_t *params); int (*rt_exec_resize)(const char *name, const char *runtime, const rt_exec_resize_params_t *params); + int (*rt_rebuild_config)(const char *name, const char *runtime, const rt_rebuild_config_params_t *params); }; int runtime_create(const char *name, const char *runtime, const rt_create_params_t *params); @@ -253,6 +259,7 @@ int runtime_attach(const char *name, const char *runtime, const rt_attach_params int runtime_update(const char *name, const char *runtime, const rt_update_params_t *params); int runtime_listpids(const char *name, const char *runtime, const rt_listpids_params_t *params, rt_listpids_out_t *out); +int runtime_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params); void free_rt_listpids_out_t(rt_listpids_out_t *out); int runtime_resize(const char *name, const char *runtime, const rt_resize_params_t *params); int runtime_exec_resize(const char *name, const char *runtime, const rt_exec_resize_params_t *params); diff --git a/src/daemon/modules/container/restore/restore.c b/src/daemon/modules/container/restore/restore.c index c26cf561..f6218fe6 100644 --- a/src/daemon/modules/container/restore/restore.c +++ b/src/daemon/modules/container/restore/restore.c @@ -16,15 +16,18 @@ #include #include #include -#include -#include #include #include #include #include +#include +#include +#include +#include + #include "isulad_config.h" -#include "isula_libutils/log.h" + #include "container_api.h" #include "supervisor.h" #include "containers_gc.h" @@ -276,9 +279,22 @@ static void restore_state(container_t *cont) #endif nret = runtime_status(id, runtime, ¶ms, &real_status); if (nret != 0) { - WARN("Failed to restore container %s, make real status to STOPPED. Due to can not load container with status %d", - id, status); - real_status.status = RUNTIME_CONTAINER_STATUS_STOPPED; + bool rebuild_config = (real_status.error_code == INVALID_CONFIG_ERR_CODE); + int tempret = -1; + // only the lcr container with a damaged config file will rebuild the config + if (rebuild_config) { + rt_rebuild_config_params_t rebuild_params = { 0 }; + rebuild_params.rootpath = cont->root_path; + nret = runtime_rebuild_config(id, runtime, &rebuild_params); + EVENT("Rebuild config for container: %s, result : %d", id, nret); + if (nret == 0) { + tempret = runtime_status(id, runtime, ¶ms, &real_status); + } + } + if (tempret != 0) { + WARN("Failed to restore container %s, make real status to STOPPED. Due to cannot load container with status %d", id, status); + real_status.status = RUNTIME_CONTAINER_STATUS_STOPPED; + } } if (real_status.status == RUNTIME_CONTAINER_STATUS_STOPPED) { diff --git a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c index f61316d0..2f42909b 100644 --- a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c +++ b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.c @@ -16,15 +16,18 @@ #include #include #include -#include -#include #include #include #include #include +#include +#include +#include +#include +#include + #include "lcr_rt_ops.h" -#include "isula_libutils/log.h" #include "engine.h" #include "error.h" #include "isulad_config.h" @@ -32,6 +35,8 @@ #include "runtime_api.h" #include "utils_file.h" +#define LCR_CONFIG_FILE "config" + bool rt_lcr_detect(const char *runtime) { /* now we just support lcr engine */ @@ -276,6 +281,17 @@ int rt_lcr_status(const char *name, const char *runtime, const rt_status_params_ nret = engine_ops->engine_get_container_status_op(name, params->rootpath, status); if (nret != 0) { ret = -1; + const char *tmpmsg = NULL; + if (engine_ops->engine_get_errmsg_op != NULL) { + tmpmsg = engine_ops->engine_get_errmsg_op(); + } + if (tmpmsg != NULL && strstr(tmpmsg, "Failed to load config") != NULL) { + status->error_code = INVALID_CONFIG_ERR_CODE; + } + isulad_set_error_message("Runtime state container error: %s", + (tmpmsg != NULL && strcmp(tmpmsg, DEF_SUCCESS_STR)) != 0 ? tmpmsg : DEF_ERR_RUNTIME_STR); + ERROR("Runtime state container error: %s", + (tmpmsg != NULL && strcmp(tmpmsg, DEF_SUCCESS_STR)) != 0 ? tmpmsg : DEF_ERR_RUNTIME_STR); goto out; } @@ -756,3 +772,80 @@ int rt_lcr_kill(const char *id, const char *runtime, const rt_kill_params_t *par return 0; } + +int rt_lcr_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params) +{ + int ret = -1; + int nret = 0; + char config_file[PATH_MAX] = { 0 }; + char bak_config_file[PATH_MAX] = { 0 }; + char oci_config_file[PATH_MAX] = { 0 }; + struct engine_operation *engine_ops = NULL; + oci_runtime_spec *oci_spec = NULL; + __isula_auto_free char *json_container = NULL; + __isula_auto_free parser_error err = NULL; + + engine_ops = engines_get_handler(runtime); + if (engine_ops == NULL || engine_ops->engine_create_op == NULL) { + ERROR("Failed to get engine rebuild config operations"); + return -1; + } + + nret = snprintf(config_file, PATH_MAX, "%s/%s/%s", params->rootpath, name, LCR_CONFIG_FILE); + if (nret < 0 || (size_t)nret >= PATH_MAX) { + ERROR("Failed to snprintf config file for container %s", name); + return -1; + } + + nret = snprintf(bak_config_file, PATH_MAX, "%s/%s/%s", params->rootpath, name, ".tmp_config_bak"); + if (nret < 0 || (size_t)nret >= PATH_MAX) { + ERROR("Failed to snprintf bak config file for container %s", name); + return -1; + } + + nret = snprintf(oci_config_file, sizeof(oci_config_file), "%s/%s/%s", params->rootpath, name, OCI_CONFIG_JSON); + if (nret < 0 || (size_t)nret >= sizeof(oci_config_file)) { + ERROR("Failed to snprintf for config json"); + return -1; + } + + oci_spec = oci_runtime_spec_parse_file(oci_config_file, NULL, &err); + if (oci_spec == NULL) { + ERROR("Failed to parse oci config file:%s", err); + return -1; + } + + // delete the bak config file to prevent the remnants of the previous bak file + if (util_fileself_exists(bak_config_file) && util_path_remove(bak_config_file) != 0) { + ERROR("Failed to remove bak_config_file for container: %s", name); + goto out; + } + + if (util_fileself_exists(config_file) && rename(config_file, bak_config_file) != 0) { + ERROR("Failed to backup old config for container: %s", name); + goto out; + } + + nret = engine_ops->engine_create_op(name, params->rootpath, (void *)oci_spec); + if (nret != 0) { + // delete the invalid config file to prevent rename failed + if (util_fileself_exists(config_file) && util_path_remove(config_file) != 0) { + WARN("Failed to remove bak_config_file for container %s", name); + } + if (util_fileself_exists(bak_config_file) && rename(bak_config_file, config_file) != 0) { + WARN("Failed to rename backup old config to config for container %s", name); + } + } + + ret = 0; + +out: + if (engine_ops != NULL && engine_ops->engine_clear_errmsg_op != NULL) { + engine_ops->engine_clear_errmsg_op(); + } + if (util_fileself_exists(bak_config_file) && util_path_remove(bak_config_file) != 0) { + WARN("Failed to remove bak_config_file for %s", name); + } + free_oci_runtime_spec(oci_spec); + return ret; +} diff --git a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.h b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.h index 5b74ad6c..7403544d 100644 --- a/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.h +++ b/src/daemon/modules/runtime/engines/lcr/lcr_rt_ops.h @@ -47,6 +47,7 @@ int rt_lcr_resources_stats(const char *name, const char *runtime, const rt_stats int rt_lcr_resize(const char *id, const char *runtime, const rt_resize_params_t *params); int rt_lcr_exec_resize(const char *id, const char *runtime, const rt_exec_resize_params_t *params); int rt_lcr_kill(const char *id, const char *runtime, const rt_kill_params_t *params); +int rt_lcr_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params); #ifdef __cplusplus } #endif diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.c b/src/daemon/modules/runtime/isula/isula_rt_ops.c index 1787170b..83214c1a 100644 --- a/src/daemon/modules/runtime/isula/isula_rt_ops.c +++ b/src/daemon/modules/runtime/isula/isula_rt_ops.c @@ -2013,3 +2013,9 @@ int rt_isula_kill(const char *id, const char *runtime, const rt_kill_params_t *p return 0; } + +// the config file of oci runtime is config.json. If it is damaged, it cannot be rebuilt. +int rt_isula_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params) +{ + return 0; +} \ No newline at end of file diff --git a/src/daemon/modules/runtime/isula/isula_rt_ops.h b/src/daemon/modules/runtime/isula/isula_rt_ops.h index 49b6cc0e..1e5e049a 100644 --- a/src/daemon/modules/runtime/isula/isula_rt_ops.h +++ b/src/daemon/modules/runtime/isula/isula_rt_ops.h @@ -46,6 +46,7 @@ int rt_isula_resources_stats(const char *name, const char *runtime, const rt_sta int rt_isula_resize(const char *id, const char *runtime, const rt_resize_params_t *params); int rt_isula_exec_resize(const char *id, const char *runtime, const rt_exec_resize_params_t *params); int rt_isula_kill(const char *id, const char *runtime, const rt_kill_params_t *params); +int rt_isula_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params); #ifdef __cplusplus } diff --git a/src/daemon/modules/runtime/runtime.c b/src/daemon/modules/runtime/runtime.c index cb383970..d9a332af 100644 --- a/src/daemon/modules/runtime/runtime.c +++ b/src/daemon/modules/runtime/runtime.c @@ -45,6 +45,7 @@ static const struct rt_ops g_lcr_rt_ops = { .rt_resize = rt_lcr_resize, .rt_exec_resize = rt_lcr_exec_resize, .rt_kill = rt_lcr_kill, + .rt_rebuild_config = rt_lcr_rebuild_config, }; static const struct rt_ops g_isula_rt_ops = { @@ -65,6 +66,7 @@ static const struct rt_ops g_isula_rt_ops = { .rt_resize = rt_isula_resize, .rt_exec_resize = rt_isula_exec_resize, .rt_kill = rt_isula_kill, + .rt_rebuild_config = rt_isula_rebuild_config, }; #ifdef ENABLE_SHIM_V2 @@ -86,6 +88,7 @@ static const struct rt_ops g_shim_rt_ops = { .rt_resize = rt_shim_resize, .rt_exec_resize = rt_shim_exec_resize, .rt_kill = rt_shim_kill, + .rt_rebuild_config = rt_shim_rebuild_config, }; #endif @@ -465,6 +468,27 @@ out: return ret; } +int runtime_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params) +{ + int ret = 0; + const struct rt_ops *ops = NULL; + + if (name == NULL || runtime == NULL || params == NULL) { + ERROR("Invalid arguments for runtime rebuild config"); + return -1; + } + + ops = rt_ops_query(runtime); + if (ops == NULL) { + ERROR("Failed to get runtime ops"); + return -1; + } + + ret = ops->rt_rebuild_config(name, runtime, params); + + return ret; +} + int runtime_resize(const char *name, const char *runtime, const rt_resize_params_t *params) { int ret = 0; diff --git a/src/daemon/modules/runtime/shim/shim_rt_ops.c b/src/daemon/modules/runtime/shim/shim_rt_ops.c index 550b17f3..56fc43c2 100644 --- a/src/daemon/modules/runtime/shim/shim_rt_ops.c +++ b/src/daemon/modules/runtime/shim/shim_rt_ops.c @@ -805,3 +805,9 @@ int rt_shim_kill(const char *id, const char *runtime, const rt_kill_params_t *pa return 0; } + +// the config file of oci runtime is config.json. If it is damaged, it cannot be rebuilt. +int rt_shim_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params) +{ + return 0; +} \ No newline at end of file diff --git a/src/daemon/modules/runtime/shim/shim_rt_ops.h b/src/daemon/modules/runtime/shim/shim_rt_ops.h index 03b7c018..2df34f4c 100644 --- a/src/daemon/modules/runtime/shim/shim_rt_ops.h +++ b/src/daemon/modules/runtime/shim/shim_rt_ops.h @@ -62,6 +62,8 @@ int rt_shim_exec_resize(const char *id, const char *runtime, const rt_exec_resiz bool is_valid_v2_runtime(const char* name); +int rt_shim_rebuild_config(const char *name, const char *runtime, const rt_rebuild_config_params_t *params); + #ifdef __cplusplus } #endif -- 2.42.0