From f4c5700bcf82bacc85e4e25b7afe94d65d3e54f4 Mon Sep 17 00:00:00 2001
From: haozi007 <liuhao27@huawei.com>
Date: Sat, 14 Nov 2020 18:44:08 +0800
Subject: [PATCH 16/17] support default container log options

Signed-off-by: haozi007 <liuhao27@huawei.com>
---
 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 <string.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include <isula_libutils/log.h>
+
+#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 <stdbool.h>
+#include <isula_libutils/json_common.h>
+
+#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 <isula_libutils/isulad_daemon_configs.h>
 #include <isula_libutils/json_common.h>
 #include <isula_libutils/oci_runtime_spec.h>
+#include <isula_libutils/log.h>
 
 #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

