From f4c5700bcf82bacc85e4e25b7afe94d65d3e54f4 Mon Sep 17 00:00:00 2001 From: haozi007 Date: Sat, 14 Nov 2020 18:44:08 +0800 Subject: [PATCH 16/17] support default container log options Signed-off-by: haozi007 --- src/cmd/isula/base/create.c | 141 +-------- src/cmd/isula/client_arguments.c | 1 - src/cmd/isulad/isulad_commands.c | 84 ++++++ src/cmd/isulad/isulad_commands.h | 38 ++- src/cmd/isulad/main.c | 73 +++++ src/cmd/options/opt_log.c | 276 ++++++++++++++++++ src/cmd/options/opt_log.h | 39 +++ src/common/constants.h | 4 + src/contrib/config/daemon.json | 3 + src/daemon/config/daemon_arguments.c | 12 +- src/daemon/config/daemon_arguments.h | 54 ++-- src/daemon/config/isulad_config.c | 84 +++++- src/daemon/config/isulad_config.h | 2 + .../executor/container_cb/execution_create.c | 150 +++++++--- .../modules/service/service_container.c | 1 + 15 files changed, 750 insertions(+), 212 deletions(-) create mode 100644 src/cmd/options/opt_log.c create mode 100644 src/cmd/options/opt_log.h diff --git a/src/cmd/isula/base/create.c b/src/cmd/isula/base/create.c index a79b18b9..87c1086b 100644 --- a/src/cmd/isula/base/create.c +++ b/src/cmd/isula/base/create.c @@ -38,6 +38,7 @@ #include "pull.h" #include "constants.h" #include "connect.h" +#include "opt_log.h" #include "utils_array.h" #include "utils_convert.h" @@ -1348,120 +1349,6 @@ static int add_new_annotation(const char *key, const char *value, struct client_ return 0; } -typedef int (*log_opt_callback_t)(const char *key, const char *value, struct client_arguments *args); - -typedef struct log_opt_parse { - const char *key; - const char *anno_key; - log_opt_callback_t cb; -} log_opt_parse_t; - -static int log_opt_common_cb(const char *key, const char *value, struct client_arguments *args) -{ - return add_new_annotation(key, value, args); -} - -static int log_opt_max_file_cb(const char *key, const char *value, struct client_arguments *args) -{ - unsigned int ptr = 0; - int ret = -1; - - if (util_safe_uint(value, &ptr)) { - return ret; - } - if (ptr == 0) { - COMMAND_ERROR("Invalid option 'max-file', value:%s", value); - return ret; - } - - return add_new_annotation(key, value, args); -} - -static int log_opt_syslog_facility(const char *key, const char *value, struct client_arguments *args) -{ -#define FACILITIES_LEN 20 - const char *facility_keys[FACILITIES_LEN] = { "kern", "user", "mail", "daemon", "auth", - "syslog", "lpr", "news", "uucp", "cron", - "authpriv", "ftp", "local0", "local1", "local2", - "local3", "local4", "local5", "local6", "local7" - }; - int i; - - for (i = 0; i < FACILITIES_LEN; i++) { - if (strcmp(facility_keys[i], value) == 0) { - break; - } - } - - if (i == FACILITIES_LEN) { - return -1; - } - - return add_new_annotation(key, value, args); -} - -static int log_opt_disable_log_cb(const char *key, const char *value, struct client_arguments *args) -{ - int ret = -1; - - if (strcmp(value, "true") == 0) { - ret = add_new_annotation(key, "none", args); - } else if (strcmp(value, "false") == 0) { - ret = 0; - } else { - COMMAND_ERROR("Invalid option 'disable-log', value:%s", value); - } - - return ret; -} - -static int log_opt_parse_options(struct client_arguments *args, const char *optkey, const char *value) -{ -#define OPTIONS_MAX 5 - log_opt_parse_t log_opts[OPTIONS_MAX] = { - { - .key = "max-size", - .anno_key = CONTAINER_LOG_CONFIG_KEY_SIZE, - .cb = &log_opt_common_cb, - }, - { - .key = "max-file", - .anno_key = CONTAINER_LOG_CONFIG_KEY_ROTATE, - .cb = &log_opt_max_file_cb, - }, - { - .key = "disable-log", - .anno_key = CONTAINER_LOG_CONFIG_KEY_FILE, - .cb = &log_opt_disable_log_cb, - }, - { - .key = "syslog-tag", - .anno_key = CONTAINER_LOG_CONFIG_KEY_SYSLOG_TAG, - .cb = &log_opt_common_cb, - }, - { - .key = "syslog-facility", - .anno_key = CONTAINER_LOG_CONFIG_KEY_SYSLOG_FACILITY, - .cb = &log_opt_syslog_facility, - }, - }; - int ret = -1; - int i; - - for (i = 0; i < OPTIONS_MAX; i++) { - if (strcmp(optkey, log_opts[i].key) == 0) { - ret = log_opts[i].cb(log_opts[i].anno_key, value, args); - break; - } - } - - if (i == OPTIONS_MAX) { - COMMAND_ERROR("Unsupported log opt: %s", optkey); - } - - return ret; -} - int log_opt_parser(struct client_arguments *args, const char *option) { int ret = -1; @@ -1504,10 +1391,22 @@ int log_opt_parser(struct client_arguments *args, const char *option) tmp[len] = '\0'; value += 1; - ret = log_opt_parse_options(args, optkey, value); + if (args->annotations == NULL) { + args->annotations = util_common_calloc_s(sizeof(json_map_string_string)); + if (args->annotations == NULL) { + COMMAND_ERROR("Out of Memory"); + goto out; + } + } + if (!parse_container_log_opt(optkey, value, args->annotations)) { + ret = -1; + goto out; + } + + ret = 0; out: - if (ret < 0) { + if (ret != 0) { COMMAND_ERROR("Invalid option: %s", option); } free(tmp); @@ -1523,21 +1422,13 @@ int callback_log_opt(command_option_t *option, const char *value) int callback_log_driver(command_option_t *option, const char *value) { -#define DRIVER_MAX 2 - const char *drivers[] = { CONTAINER_LOG_CONFIG_JSON_FILE_DRIVER, CONTAINER_LOG_CONFIG_SYSLOG_DRIVER }; - int i = 0; struct client_arguments *args = (struct client_arguments *)option->data; if (value == NULL) { return -1; } - for (; i < DRIVER_MAX; i++) { - if (strcmp(value, drivers[i]) == 0) { - break; - } - } - if (i == DRIVER_MAX) { + if (!check_opt_container_log_driver(value)) { return -1; } diff --git a/src/cmd/isula/client_arguments.c b/src/cmd/isula/client_arguments.c index ad6ba40c..ffe40c2e 100644 --- a/src/cmd/isula/client_arguments.c +++ b/src/cmd/isula/client_arguments.c @@ -123,7 +123,6 @@ int client_arguments_init(struct client_arguments *args) } else { args->socket = util_strdup_s(DEFAULT_UNIX_SOCKET); } - args->log_driver = util_strdup_s("json-file"); (void)memset(&args->custom_conf, 0, sizeof(struct custom_configs)); (void)memset(&args->cr, 0, sizeof(struct args_cgroup_resources)); diff --git a/src/cmd/isulad/isulad_commands.c b/src/cmd/isulad/isulad_commands.c index 11e166fc..d0ab029c 100644 --- a/src/cmd/isulad/isulad_commands.c +++ b/src/cmd/isulad/isulad_commands.c @@ -32,6 +32,7 @@ #include "utils_string.h" #include "utils_verify.h" #include "opt_ulimit.h" +#include "opt_log.h" const char isulad_desc[] = "GLOBAL OPTIONS:"; const char isulad_usage[] = "[global options]"; @@ -103,6 +104,89 @@ out: return ret; } +int server_callback_container_log_driver(command_option_t *option, const char *value) +{ + int ret = 0; + struct service_arguments *args = NULL; + + if (option == NULL || value == NULL) { + COMMAND_ERROR("Invalid input arguments"); + ret = -1; + goto out; + } + if (!check_opt_container_log_driver(value)) { + ret = -1; + goto out; + } + + args = (struct service_arguments *)option->data; + + free(args->json_confs->container_log->driver); + args->json_confs->container_log->driver = util_strdup_s(value); + +out: + return ret; +} + +int server_callback_container_log(command_option_t *option, const char *value) +{ + int ret = 0; + struct service_arguments *args = NULL; + json_map_string_string *log_opts = NULL; + char **split_opts = NULL; + size_t i; + + if (option == NULL || value == NULL) { + COMMAND_ERROR("Invalid input arguments"); + ret = -1; + goto out; + } + split_opts = util_string_split_multi(value, '='); + // value must be format of 'key = value' + if (util_array_len((const char **)split_opts) != 2) { + COMMAND_ERROR("Invalid input arguments: %s", value); + ret = -1; + goto out; + } + + if (!check_raw_log_opt(split_opts[0])) { + COMMAND_ERROR("Unsupport container log key: %s", split_opts[0]); + ret = -1; + goto out; + } + + args = (struct service_arguments *)option->data; + if (args->json_confs->container_log->opts == NULL) { + args->json_confs->container_log->opts = util_common_calloc_s(sizeof(json_map_string_string)); + } + log_opts = args->json_confs->container_log->opts; + if (log_opts == NULL) { + COMMAND_ERROR("Out of memory"); + ret = -1; + goto out; + } + + for (i = 0; i < log_opts->len; i++) { + // just update found key-value + if (strcmp(split_opts[0], log_opts->keys[i]) == 0) { + free(log_opts->values[i]); + log_opts->values[i] = util_strdup_s(split_opts[1]); + goto out; + } + } + + ret = append_json_map_string_string(log_opts, split_opts[0], split_opts[1]); + if (ret != 0) { + COMMAND_ERROR("Out of memory"); + ret = -1; + goto out; + } + +out: + util_free_array(split_opts); + return ret; +} + static void command_init_isulad(command_t *self, command_option_t *options, int options_len, int argc, const char **argv, const char *description, const char *usage) { diff --git a/src/cmd/isulad/isulad_commands.h b/src/cmd/isulad/isulad_commands.h index 78ec5846..02007f3c 100644 --- a/src/cmd/isulad/isulad_commands.h +++ b/src/cmd/isulad/isulad_commands.h @@ -37,14 +37,14 @@ int update_hosts(struct service_arguments *args); int update_default_ulimit(struct service_arguments *args); int command_default_ulimit_append(command_option_t *option, const char *arg); -#define ISULAD_OPTIONS(cmdargs) \ - { CMD_OPT_TYPE_CALLBACK, \ - false, \ - "host", \ - 'H', \ - &(cmdargs)->hosts, \ - "The socket name used to create gRPC server", \ - command_valid_socket_append_array }, \ +#define ISULAD_OPTIONS(cmdargs) \ + { CMD_OPT_TYPE_CALLBACK, \ + false, \ + "host", \ + 'H', \ + &(cmdargs)->hosts, \ + "The socket name used to create gRPC server", \ + command_valid_socket_append_array }, \ { CMD_OPT_TYPE_STRING_DUP, false, "pidfile", 'p', &(cmdargs)->json_confs->pidfile, \ "Save pid into this file", NULL }, \ { CMD_OPT_TYPE_BOOL, false, "help", 0, &(cmdargs)->help, "Show help", NULL }, \ @@ -99,13 +99,27 @@ int command_default_ulimit_append(command_option_t *option, const char *arg); (cmdargs), \ "Set daemon log driver options, such as: log-path=/tmp/logs/ to set directory where to store daemon logs", \ server_callback_log_opt }, \ + { CMD_OPT_TYPE_CALLBACK, \ + false, \ + "container-log-driver", \ + 0, \ + (cmdargs), \ + "Set default container log driver, such as: json-file", \ + server_callback_container_log_driver }, \ + { CMD_OPT_TYPE_CALLBACK, \ + false, \ + "container-log-opts", \ + 0, \ + (cmdargs), \ + "Set default container log driver options, such as: max-file=7 to set max number of container log files", \ + server_callback_container_log }, \ { CMD_OPT_TYPE_BOOL, false, "version", 'V', &(cmdargs)->version, "Print the version", NULL }, \ { CMD_OPT_TYPE_STRING_DUP, \ false, \ "group", \ 'G', \ &(cmdargs)->json_confs->group, \ - "Group for the unix socket(default is isula)", \ + "Group for the unix socket(default is isula)", \ NULL }, \ { CMD_OPT_TYPE_STRING_DUP, \ false, \ @@ -249,9 +263,9 @@ int command_default_ulimit_append(command_option_t *option, const char *arg); &(cmdargs)->json_confs->websocket_server_listening_port, \ "CRI websocket streaming service listening port (default 10350)", \ command_convert_uint }, \ - { \ - CMD_OPT_TYPE_BOOL, false, "selinux-enabled", 0, &(cmdargs)->json_confs->selinux_enabled, \ - "Enable selinux support", NULL \ + { CMD_OPT_TYPE_BOOL, \ + false, "selinux-enabled", 0, &(cmdargs)->json_confs->selinux_enabled, \ + "Enable selinux support", NULL \ } #ifdef __cplusplus diff --git a/src/cmd/isulad/main.c b/src/cmd/isulad/main.c index bef78f87..ce93eaa0 100644 --- a/src/cmd/isulad/main.c +++ b/src/cmd/isulad/main.c @@ -70,6 +70,7 @@ #include "utils_string.h" #include "utils_verify.h" #include "volume_api.h" +#include "opt_log.h" #ifdef GRPC_CONNECTOR #include "clibcni/api.h" @@ -836,6 +837,73 @@ static int configure_kernel_security_support(const struct service_arguments *arg } #endif +static int use_default_log_opts_for_json_file(bool rotate_found, bool size_found, + isulad_daemon_configs_container_log *conf) +{ + int nret = 0; + + if (conf->opts == NULL) { + conf->opts = util_common_calloc_s(sizeof(json_map_string_string)); + } + if (conf->opts == NULL) { + ERROR("Out of memory"); + return -1; + } + + if (!rotate_found) { + nret = append_json_map_string_string(conf->opts, CONTAINER_LOG_CONFIG_KEY_ROTATE, "7"); + if (nret != 0) { + ERROR("Out of memory"); + return -1; + } + } + + if (!size_found) { + nret = append_json_map_string_string(conf->opts, CONTAINER_LOG_CONFIG_KEY_SIZE, "1MB"); + if (nret != 0) { + ERROR("Out of memory"); + return -1; + } + } + + return 0; +} + +static int update_container_log_configs(isulad_daemon_configs_container_log *conf) +{ + bool rotate_found = false; + bool size_found = false; + size_t i; + + if (conf->driver == NULL) { + conf->driver = util_strdup_s(CONTAINER_LOG_CONFIG_JSON_FILE_DRIVER); + } + + if (!parse_container_log_opts(&conf->opts)) { + return -1; + } + + /* validate daemon container log configs */ + for (i = 0; conf->opts != NULL && i < conf->opts->len; i++) { + if (!check_opt_container_log_opt(conf->driver, conf->opts->keys[i])) { + return -1; + } + + if (strcmp(CONTAINER_LOG_CONFIG_KEY_ROTATE, conf->opts->keys[i]) == 0) { + rotate_found = true; + } else if (strcmp(CONTAINER_LOG_CONFIG_KEY_SIZE, conf->opts->keys[i]) == 0) { + size_found = true; + } + } + + // set default log opts for json file driver + if (strcmp(conf->driver, CONTAINER_LOG_CONFIG_JSON_FILE_DRIVER) == 0) { + return use_default_log_opts_for_json_file(rotate_found, size_found, conf); + } + + return 0; +} + static int update_server_args(struct service_arguments *args) { int ret = 0; @@ -860,6 +928,11 @@ static int update_server_args(struct service_arguments *args) goto out; } + if (update_container_log_configs(args->json_confs->container_log) != 0) { + ret = -1; + goto out; + } + /* check args */ if (check_args(args)) { ret = -1; diff --git a/src/cmd/options/opt_log.c b/src/cmd/options/opt_log.c new file mode 100644 index 00000000..f6c18b23 --- /dev/null +++ b/src/cmd/options/opt_log.c @@ -0,0 +1,276 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: haozi007 + * Create: 2020-11-16 + * Description: provide log options parse function + ******************************************************************************/ +#include "opt_log.h" + +#include +#include +#include + +#include + +#include "constants.h" +#include "utils.h" +#include "utils_array.h" +#include "utils_convert.h" +#include "utils_string.h" + +#define DRIVER_MAX 2 + +typedef int (*log_opt_callback_t)(const char *key, const char *value, char **parsed_val); + +typedef struct log_opt_parse { + const char *key; + const char *real_key; + log_opt_callback_t cb; +} log_opt_parse_t; + +static int log_opt_common_cb(const char *key, const char *value, char **parsed_val) +{ + *parsed_val = util_strdup_s(value); + return 0; +} + +static int log_opt_max_file_cb(const char *key, const char *value, char **parsed_val) +{ + unsigned int ptr = 0; + int ret = -1; + + if (util_safe_uint(value, &ptr)) { + return ret; + } + if (ptr == 0) { + ERROR("Invalid option 'max-file', value:%s", value); + return ret; + } + + *parsed_val = util_strdup_s(value); + return 0; +} + +static int log_opt_syslog_facility(const char *key, const char *value, char **parsed_val) +{ + const char *facility_values[] = { "kern", "user", "mail", "daemon", "auth", + "syslog", "lpr", "news", "uucp", "cron", + "authpriv", "ftp", "local0", "local1", "local2", + "local3", "local4", "local5", "local6", "local7" + }; + int i; + size_t f_len = sizeof(facility_values) / sizeof(const char *); + + for (i = 0; i < f_len; i++) { + if (strcmp(facility_values[i], value) == 0) { + break; + } + } + + if (i == f_len) { + ERROR("Invalid option 'syslog-facility', value:%s", value); + return -1; + } + + *parsed_val = util_strdup_s(value); + return 0; +} + +static int log_opt_disable_log_cb(const char *key, const char *value, char **parsed_val) +{ + int ret = -1; + + if (strcmp(value, "true") == 0) { + *parsed_val = util_strdup_s("none"); + ret = 0; + } else if (strcmp(value, "false") == 0) { + ret = 0; + } + + if (ret != 0) { + ERROR("Invalid option 'disable-log', value:%s", value); + } + + return ret; +} + +bool parse_container_log_opt(const char *key, const char *val, json_map_string_string *opts) +{ +#define LOG_PARSER_MAX 5 + size_t i, j; + log_opt_parse_t support_parsers[LOG_PARSER_MAX] = { + { + .key = "max-size", + .real_key = CONTAINER_LOG_CONFIG_KEY_SIZE, + .cb = &log_opt_common_cb, + }, + { + .key = "max-file", + .real_key = CONTAINER_LOG_CONFIG_KEY_ROTATE, + .cb = &log_opt_max_file_cb, + }, + { + .key = "disable-log", + .real_key = CONTAINER_LOG_CONFIG_KEY_FILE, + .cb = &log_opt_disable_log_cb, + }, + { + .key = "syslog-tag", + .real_key = CONTAINER_LOG_CONFIG_KEY_SYSLOG_TAG, + .cb = &log_opt_common_cb, + }, + { + .key = "syslog-facility", + .real_key = CONTAINER_LOG_CONFIG_KEY_SYSLOG_FACILITY, + .cb = &log_opt_syslog_facility, + }, + }; + + if (key == NULL || opts == NULL) { + return false; + } + + for (i = 0; i < LOG_PARSER_MAX; i++) { + if (strcmp(key, support_parsers[i].key) == 0) { + char *parsed_val = NULL; + int nret; + + nret = support_parsers[i].cb(support_parsers[i].real_key, val, &parsed_val); + if (nret != 0) { + return false; + } + if (parsed_val == NULL) { + return true; + } + + // check whether seted option, if setted, ust replace + for (j = 0; j < opts->len; j++) { + if (strcmp(opts->keys[j], support_parsers[i].real_key) == 0) { + free(opts->values[j]); + opts->values[j] = parsed_val; + return true; + } + } + nret = append_json_map_string_string(opts, support_parsers[i].real_key, parsed_val); + return true; + } + } + ERROR("Unknow log opts: %s = %s", key, val); + return false; +} + +bool parse_container_log_opts(json_map_string_string **opts) +{ + size_t i; + json_map_string_string *result = NULL; + + if (opts == NULL || *opts == NULL) { + return true; + } + result = util_common_calloc_s(sizeof(json_map_string_string)); + if (result == NULL) { + ERROR("Out of memory"); + return false; + } + + for (i = 0; i < (*opts)->len; i++) { + if ((*opts)->values[i] == NULL || strlen((*opts)->values[i]) > OPT_MAX_LEN) { + ERROR("Too large value: %s for key:%s", (*opts)->values[i], (*opts)->keys[i]); + free_json_map_string_string(result); + return false; + } + + if (!parse_container_log_opt((*opts)->keys[i], (*opts)->values[i], result)) { + free_json_map_string_string(result); + return false; + } + } + + free_json_map_string_string(*opts); + *opts = result; + return true; +} + +bool check_opt_container_log_opt(const char *driver, const char *opt_key) +{ +#define DRIVER_MAX 2 +#define MAX_SUPPORT_KEY_LEN 3 + const char *support_keys[][MAX_SUPPORT_KEY_LEN] = { + { CONTAINER_LOG_CONFIG_KEY_FILE, CONTAINER_LOG_CONFIG_KEY_ROTATE, CONTAINER_LOG_CONFIG_KEY_SIZE }, + { CONTAINER_LOG_CONFIG_KEY_SYSLOG_TAG, CONTAINER_LOG_CONFIG_KEY_SYSLOG_FACILITY, NULL} + }; + const char *driver_idx[] = { CONTAINER_LOG_CONFIG_JSON_FILE_DRIVER, CONTAINER_LOG_CONFIG_SYSLOG_DRIVER }; + size_t i, idx; + + if (driver == NULL || opt_key == NULL) { + return false; + } + for (idx = 0; idx < DRIVER_MAX; idx++) { + if (strcmp(driver_idx[idx], driver) == 0) { + break; + } + } + if (idx == DRIVER_MAX) { + ERROR("Unsupport driver: %s", driver); + return false; + } + + for (i = 0; i < MAX_SUPPORT_KEY_LEN; i++) { + if (support_keys[idx][i] == NULL) { + break; + } + if (strcmp(support_keys[idx][i], opt_key) == 0) { + return true; + } + } + + ERROR("driver: %s, unsupport opts: %s", driver, opt_key); + return false; +} + +bool check_raw_log_opt(const char *key) +{ + size_t i; + const char *support_keys[] = { + "max-size", "max-file", "disable-log", "syslog-tag", "syslog-facility" + }; + + if (key == NULL) { + return false; + } + + for (i = 0; i < sizeof(support_keys) / sizeof(const char *); i++) { + if (strcmp(key, support_keys[i]) == 0) { + return true; + } + } + + return false; +} + +bool check_opt_container_log_driver(const char *driver) +{ + const char *supported_drivers[] = { CONTAINER_LOG_CONFIG_JSON_FILE_DRIVER, CONTAINER_LOG_CONFIG_SYSLOG_DRIVER }; + int i = 0; + + if (driver == NULL) { + return false; + } + + for (; i < DRIVER_MAX; i++) { + if (strcmp(driver, supported_drivers[i]) == 0) { + return true; + } + } + + return false; +} + diff --git a/src/cmd/options/opt_log.h b/src/cmd/options/opt_log.h new file mode 100644 index 00000000..f9daa02d --- /dev/null +++ b/src/cmd/options/opt_log.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved. + * iSulad licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: haozi007 + * Create: 2020-11-13 + * Description: provide log options parse function + ******************************************************************************/ +#ifndef CMD_OPTIONS_LOG_H +#define CMD_OPTIONS_LOG_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool check_raw_log_opt(const char *key); + +bool check_opt_container_log_opt(const char *driver, const char *opt); + +bool check_opt_container_log_driver(const char *driver); + +bool parse_container_log_opt(const char *key, const char *val, json_map_string_string *opts); + +bool parse_container_log_opts(json_map_string_string **opts); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/common/constants.h b/src/common/constants.h index 457e2423..dd2f3e5e 100644 --- a/src/common/constants.h +++ b/src/common/constants.h @@ -82,6 +82,8 @@ extern "C" { #define CONTAINER_LOG_CONFIG_JSON_FILE_DRIVER "json-file" #define CONTAINER_LOG_CONFIG_SYSLOG_DRIVER "syslog" + +#define CONTAINER_LOG_CONFIG_KEY_PREFIX "log.console." #define CONTAINER_LOG_CONFIG_KEY_DRIVER "log.console.driver" #define CONTAINER_LOG_CONFIG_KEY_FILE "log.console.file" #define CONTAINER_LOG_CONFIG_KEY_ROTATE "log.console.filerotate" @@ -121,6 +123,8 @@ extern "C" { #define MAX_HOSTS 10 +#define OPT_MAX_LEN 255 + #define EVENT_ARGS_MAX 255 #define EVENT_EXTRA_ANNOTATION_MAX 255 diff --git a/src/contrib/config/daemon.json b/src/contrib/config/daemon.json index 9ffb08ef..d2ce4d02 100644 --- a/src/contrib/config/daemon.json +++ b/src/contrib/config/daemon.json @@ -13,6 +13,9 @@ "max-size": "30KB" }, "log-driver": "stdout", + "container-log": { + "driver": "json-file" + }, "hook-spec": "/etc/default/isulad/hooks/default.json", "start-timeout": "2m", "storage-driver": "overlay2", diff --git a/src/daemon/config/daemon_arguments.c b/src/daemon/config/daemon_arguments.c index ef287645..ba41a9a5 100644 --- a/src/daemon/config/daemon_arguments.c +++ b/src/daemon/config/daemon_arguments.c @@ -137,6 +137,14 @@ int service_arguments_init(struct service_arguments *args) args->max_file = 7; args->max_size = 1024 * 1024; + // init container log configs + args->json_confs->container_log = (isulad_daemon_configs_container_log *)util_common_calloc_s(sizeof( + isulad_daemon_configs_container_log)); + if (args->json_confs->container_log == NULL) { + ERROR("Out of memory"); + goto free_out; + } + args->json_confs->pidfile = util_strdup_s("/var/run/isulad.pid"); args->json_confs->storage_driver = util_strdup_s("overlay2"); args->json_confs->native_umask = util_strdup_s(UMASK_SECURE); @@ -149,7 +157,6 @@ int service_arguments_init(struct service_arguments *args) *(args->json_confs->use_decrypted_key) = true; args->json_confs->insecure_skip_verify_enforce = false; - args->image_opt_timeout = 5 * 60; // default image operation timeout 300s if (set_daemon_default_tls_options(args) != 0) { goto free_out; } @@ -241,6 +248,7 @@ int server_log_opt_parser(struct service_arguments *args, const char *option) ret = append_json_map_string_string(args->json_confs->log_opts, key, value); } + tmp[len] = '='; out: free(tmp); return ret; @@ -310,4 +318,4 @@ void free_default_ulimit(host_config_ulimits_element **default_ulimit) free_host_config_ulimits_element(*p); } free(default_ulimit); -} \ No newline at end of file +} diff --git a/src/daemon/config/daemon_arguments.h b/src/daemon/config/daemon_arguments.h index 77feb4d1..54099c81 100644 --- a/src/daemon/config/daemon_arguments.h +++ b/src/daemon/config/daemon_arguments.h @@ -31,38 +31,40 @@ extern "C" { typedef void (*service_arguments_help_t)(void); struct service_arguments { - char *progname; service_arguments_help_t print_help; - bool quiet; - bool help; - bool version; - char **hosts; - size_t hosts_len; - - // struct service_arguments *server_conf; + struct { /* common args */ + char *progname; + bool quiet; + bool help; + bool version; + char **hosts; + size_t hosts_len; + unsigned int websocket_server_listening_port; + }; + + struct { /* default configs for container */ + // daemon hooks config + oci_runtime_spec_hooks *hooks; + + host_config_ulimits_element **default_ulimit; + size_t default_ulimit_len; + + unsigned int start_timeout; + }; + + struct { /* daemon log configs */ + unsigned int log_file_mode; + char *logpath; + int64_t max_size; + int max_file; + }; + + // store all daemon.json configs isulad_daemon_configs *json_confs; - /* parsed configs */ - oci_runtime_spec_hooks *hooks; - - unsigned int start_timeout; - unsigned int image_opt_timeout; - - /* log-opts */ - unsigned int log_file_mode; - char *logpath; - int64_t max_size; - int max_file; - - /* default configs */ - host_config_ulimits_element **default_ulimit; - size_t default_ulimit_len; - unsigned int websocket_server_listening_port; - // remaining arguments char * const *argv; - int argc; }; diff --git a/src/daemon/config/isulad_config.c b/src/daemon/config/isulad_config.c index f6e5ffdb..314545fa 100644 --- a/src/daemon/config/isulad_config.c +++ b/src/daemon/config/isulad_config.c @@ -27,9 +27,9 @@ #include #include #include +#include #include "constants.h" -#include "isula_libutils/log.h" #include "utils.h" #include "sysinfo.h" #include "err_msg.h" @@ -815,6 +815,61 @@ out: return logdriver; } +/* conf get default container log opts */ +int conf_get_container_log_opts(isulad_daemon_configs_container_log **opts) +{ + struct service_arguments *conf = NULL; + isulad_daemon_configs_container_log *result = NULL; + isulad_daemon_configs_container_log *work = NULL; + size_t i; + int ret = 0; + + if (isulad_server_conf_rdlock() != 0) { + return -1; + } + + conf = conf_get_server_conf(); + if (conf == NULL || conf->json_confs->container_log == NULL) { + goto out; + } + work = conf->json_confs->container_log; + + result = util_common_calloc_s(sizeof(isulad_daemon_configs_container_log)); + if (result == NULL) { + ERROR("Out of memory"); + ret = -1; + goto out; + } + result->driver = util_strdup_s(work->driver); + if (work->opts == NULL) { + *opts = result; + result = NULL; + goto out; + } + if (work->opts->len > 0) { + result->opts = util_common_calloc_s(sizeof(json_map_string_string)); + if (result->opts == NULL) { + ERROR("Out of memory"); + ret = -1; + goto out; + } + } + for (i = 0; i < work->opts->len; i++) { + if (append_json_map_string_string(result->opts, work->opts->keys[i], work->opts->values[i]) != 0) { + ERROR("Out of memory"); + ret = -1; + goto out; + } + } + + *opts = result; + result = NULL; +out: + (void)isulad_server_conf_unlock(); + free_isulad_daemon_configs_container_log(result); + return ret; +} + /* conf get image layer check flag */ bool conf_get_image_layer_check_flag() { @@ -1311,7 +1366,7 @@ static int merge_hosts_conf_into_global(struct service_arguments *args, const is return 0; } -static int merge_logs_conf_into_global(struct service_arguments *args, isulad_daemon_configs *tmp_json_confs) +static int do_merge_daemon_logs_conf(struct service_arguments *args, isulad_daemon_configs *tmp_json_confs) { size_t i; @@ -1334,6 +1389,31 @@ static int merge_logs_conf_into_global(struct service_arguments *args, isulad_da return 0; } +// just mask isulad config to args +static int do_merge_container_logs_conf(struct service_arguments *args, isulad_daemon_configs *tmp_json_confs) +{ + if (tmp_json_confs->container_log == NULL) { + return 0; + } + + // do not check valid of json log opts at here; + // while all config ready to do check. + free_isulad_daemon_configs_container_log(args->json_confs->container_log); + args->json_confs->container_log = tmp_json_confs->container_log; + tmp_json_confs->container_log = NULL; + + return 0; +} + +static int merge_logs_conf_into_global(struct service_arguments *args, isulad_daemon_configs *tmp_json_confs) +{ + if (do_merge_daemon_logs_conf(args, tmp_json_confs)) { + return -1; + } + + return do_merge_container_logs_conf(args, tmp_json_confs); +} + static int merge_authorization_conf_into_global(struct service_arguments *args, isulad_daemon_configs *tmp_json_confs) { args->json_confs->tls = tmp_json_confs->tls; diff --git a/src/daemon/config/isulad_config.h b/src/daemon/config/isulad_config.h index b5c64c54..fb523e5d 100644 --- a/src/daemon/config/isulad_config.h +++ b/src/daemon/config/isulad_config.h @@ -51,6 +51,8 @@ char *conf_get_isulad_log_gather_fifo_path(); int conf_get_cgroup_cpu_rt(int64_t *cpu_rt_period, int64_t *cpu_rt_runtime); +int conf_get_container_log_opts(isulad_daemon_configs_container_log **opts); + char *conf_get_isulad_log_file(); char *conf_get_engine_log_file(); char *conf_get_enable_plugins(); diff --git a/src/daemon/executor/container_cb/execution_create.c b/src/daemon/executor/container_cb/execution_create.c index 188d58b2..c2ddf88b 100644 --- a/src/daemon/executor/container_cb/execution_create.c +++ b/src/daemon/executor/container_cb/execution_create.c @@ -57,6 +57,7 @@ #include "utils_timestamp.h" #include "utils_verify.h" #include "selinux_label.h" +#include "opt_log.h" static int do_init_cpurt_cgroups_path(const char *path, int recursive_depth, const char *mnt_root, int64_t cpu_rt_period, int64_t cpu_rt_runtime); @@ -213,67 +214,128 @@ static container_config *get_container_spec_from_request(const container_create_ return container_spec; } -static int add_default_log_config_to_container_spec(const char *id, const char *runtime_root, - container_config *container_spec) +static void set_container_log_config_driver(isulad_daemon_configs_container_log *opts, container_config *container_spec) { - int ret = 0; - int i = 0; - bool file_found = false; - bool rotate_found = false; - bool size_found = false; + if (container_spec->log_driver != NULL) { + return; + } + + // use daemon container log driver + container_spec->log_driver = util_strdup_s(opts->driver); + if (container_spec->log_driver != NULL) { + return; + } + + // use default container log driver + container_spec->log_driver = util_strdup_s(CONTAINER_LOG_CONFIG_JSON_FILE_DRIVER); +} - /* generate default log path */ - if (container_spec->log_driver != NULL && - strcmp(CONTAINER_LOG_CONFIG_SYSLOG_DRIVER, container_spec->log_driver) == 0) { +static int merge_container_log_config_opts(const char *daemon_driver, const json_map_string_string *daemon_opts, + container_config *spec) +{ + size_t i, j; + + if (daemon_driver == NULL || strcmp(daemon_driver, spec->log_driver) != 0) { + // daemon driver different with spec, just ignore log opts of daemon return 0; } - if (container_spec->annotations == NULL) { - container_spec->annotations = util_common_calloc_s(sizeof(json_map_string_string)); + // merge daemon container log opts into spec + for (i = 0; daemon_opts != NULL && i < daemon_opts->len; i++) { + for (j = 0; j < spec->annotations->len; j++) { + if (strcmp(spec->annotations->keys[j], daemon_opts->keys[i]) == 0) { + break; + } + } + if (j == spec->annotations->len && + append_json_map_string_string(spec->annotations, daemon_opts->keys[i], daemon_opts->values[i]) != 0) { + ERROR("Out of memory"); + return -1; + } } - if (container_spec->annotations == NULL) { + + return 0; +} + +static int do_set_default_log_path_for_json_file(const char *id, const char *root, bool file_found, + container_config *spec) +{ + int nret = 0; + char default_path[PATH_MAX] = { 0 }; + + nret = snprintf(default_path, PATH_MAX, "%s/%s/console.log", root, id); + if (nret < 0 || nret >= PATH_MAX) { + ERROR("Create default log path for container %s failed", id); + return -1; + } + nret = append_json_map_string_string(spec->annotations, CONTAINER_LOG_CONFIG_KEY_FILE, default_path); + if (nret != 0) { ERROR("Out of memory"); - ret = -1; - goto out; + return -1; } - for (; i < container_spec->annotations->len; i++) { - const char *tmp_key = container_spec->annotations->keys[i]; + return 0; +} + +static int do_check_container_log_config_opts(const char *id, const char *root, container_config *spec) +{ + size_t i; + bool file_found = false; + + // check log opts is support by driver + for (i = 0; i < spec->annotations->len; i++) { + const char *tmp_key = spec->annotations->keys[i]; + if (strncmp(tmp_key, CONTAINER_LOG_CONFIG_KEY_PREFIX, strlen(CONTAINER_LOG_CONFIG_KEY_PREFIX)) != 0) { + // ignore other configs + continue; + } + DEBUG("check log opt key: %s for driver: %s", tmp_key, spec->log_driver); + if (!check_opt_container_log_opt(spec->log_driver, tmp_key)) { + isulad_set_error_message("container log driver: %s, unsupport: %s", spec->log_driver, tmp_key); + return -1; + } + if (strcmp(CONTAINER_LOG_CONFIG_KEY_FILE, tmp_key) == 0) { file_found = true; - } else if (strcmp(CONTAINER_LOG_CONFIG_KEY_ROTATE, tmp_key) == 0) { - rotate_found = true; - } else if (strcmp(CONTAINER_LOG_CONFIG_KEY_SIZE, tmp_key) == 0) { - size_found = true; } } - if (!file_found) { - char default_path[PATH_MAX] = { 0 }; - int nret = snprintf(default_path, PATH_MAX, "%s/%s/console.log", runtime_root, id); - if (nret < 0 || nret >= PATH_MAX) { - ERROR("Create default log path for container %s failed", id); - ret = -1; - goto out; - } - ret = append_json_map_string_string(container_spec->annotations, CONTAINER_LOG_CONFIG_KEY_FILE, default_path); - if (ret != 0) { - goto out; - } + + if (!file_found && strcmp(spec->log_driver, CONTAINER_LOG_CONFIG_JSON_FILE_DRIVER) == 0) { + return do_set_default_log_path_for_json_file(id, root, file_found, spec); } - if (!rotate_found) { - ret = append_json_map_string_string(container_spec->annotations, CONTAINER_LOG_CONFIG_KEY_ROTATE, "7"); - if (ret != 0) { - goto out; - } + + return 0; +} + +static int set_container_log_config_to_container_spec(const char *id, const char *runtime_root, + container_config *container_spec) +{ + int ret = 0; + isulad_daemon_configs_container_log *daemon_container_opts = NULL; + + if (conf_get_container_log_opts(&daemon_container_opts) != 0) { + return -1; } - if (!size_found) { - ret = append_json_map_string_string(container_spec->annotations, CONTAINER_LOG_CONFIG_KEY_SIZE, "30KB"); - if (ret != 0) { - goto out; - } + + set_container_log_config_driver(daemon_container_opts, container_spec); + + if (container_spec->annotations == NULL) { + container_spec->annotations = util_common_calloc_s(sizeof(json_map_string_string)); + } + if (container_spec->annotations == NULL) { + ERROR("Out of memory"); + ret = -1; + goto out; + } + + ret = merge_container_log_config_opts(daemon_container_opts->driver, daemon_container_opts->opts, container_spec); + if (ret != 0) { + goto out; } + ret = do_check_container_log_config_opts(id, runtime_root, container_spec); out: + free_isulad_daemon_configs_container_log(daemon_container_opts); return ret; } @@ -287,7 +349,7 @@ static container_config *get_container_spec(const char *id, const char *runtime_ return NULL; } - if (add_default_log_config_to_container_spec(id, runtime_root, container_spec)) { + if (set_container_log_config_to_container_spec(id, runtime_root, container_spec)) { goto error_out; } diff --git a/src/daemon/modules/service/service_container.c b/src/daemon/modules/service/service_container.c index 529a68de..ae5db17d 100644 --- a/src/daemon/modules/service/service_container.c +++ b/src/daemon/modules/service/service_container.c @@ -770,6 +770,7 @@ static int do_start_container(container_t *cont, const char *console_fifos[], bo goto close_exit_fd; } + create_params.bundle = bundle; create_params.state = cont->state_path; create_params.oci_config_data = oci_spec; -- 2.25.1