1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198
|
#include "cli.h"
#include "globals.h"
#include "ctr_logging.h"
#include "config.h"
#include "utils.h"
#include <glib.h>
#include <glib-unix.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef __linux__
#include <linux/limits.h>
#endif
gboolean opt_version = FALSE;
gboolean opt_terminal = FALSE;
gboolean opt_stdin = FALSE;
gboolean opt_leave_stdin_open = FALSE;
gboolean opt_syslog = FALSE;
gboolean is_cgroup_v2 = FALSE;
char *cgroup2_path = NULL;
char *opt_cid = NULL;
char *opt_cuuid = NULL;
char *opt_name = NULL;
char *opt_runtime_path = NULL;
char *opt_bundle_path = NULL;
char *opt_persist_path = NULL;
char *opt_container_pid_file = NULL;
char *opt_conmon_pid_file = NULL;
gboolean opt_systemd_cgroup = FALSE;
gboolean opt_no_pivot = FALSE;
gboolean opt_attach = FALSE;
char *opt_exec_process_spec = NULL;
gboolean opt_exec = FALSE;
int opt_api_version = 0;
char *opt_restore_path = NULL;
gchar **opt_runtime_opts = NULL;
gchar **opt_runtime_args = NULL;
gchar **opt_log_path = NULL;
char *opt_exit_dir = NULL;
int opt_timeout = 0;
int64_t opt_log_size_max = -1;
int64_t opt_log_global_size_max = -1;
char *opt_socket_path = DEFAULT_SOCKET_PATH;
gboolean opt_no_new_keyring = FALSE;
char *opt_exit_command = NULL;
gchar **opt_exit_args = NULL;
int opt_exit_delay = 0;
gboolean opt_replace_listen_pid = FALSE;
char *opt_log_level = NULL;
char *opt_log_tag = NULL;
gboolean opt_sync = FALSE;
gboolean opt_no_sync_log = FALSE;
char *opt_sdnotify_socket = NULL;
gboolean opt_full_attach_path = FALSE;
char *opt_seccomp_notify_socket = NULL;
char *opt_seccomp_notify_plugins = NULL;
GOptionEntry opt_entries[] = {
{"api-version", 0, 0, G_OPTION_ARG_NONE, &opt_api_version, "Conmon API version to use", NULL},
{"bundle", 'b', 0, G_OPTION_ARG_STRING, &opt_bundle_path, "Location of the OCI Bundle path", NULL},
{"cid", 'c', 0, G_OPTION_ARG_STRING, &opt_cid, "Identification of Container", NULL},
{"conmon-pidfile", 'P', 0, G_OPTION_ARG_STRING, &opt_conmon_pid_file, "PID file for the conmon process", NULL},
{"container-pidfile", 'p', 0, G_OPTION_ARG_STRING, &opt_container_pid_file, "PID file for the initial pid inside of container",
NULL},
{"cuuid", 'u', 0, G_OPTION_ARG_STRING, &opt_cuuid, "Container UUID", NULL},
{"exec", 'e', 0, G_OPTION_ARG_NONE, &opt_exec, "Exec a command into a running container", NULL},
{"exec-attach", 0, 0, G_OPTION_ARG_NONE, &opt_attach, "Attach to an exec session", NULL},
{"exec-process-spec", 0, 0, G_OPTION_ARG_STRING, &opt_exec_process_spec, "Path to the process spec for execution", NULL},
{"exit-command", 0, 0, G_OPTION_ARG_STRING, &opt_exit_command,
"Path to the program to execute when the container terminates its execution", NULL},
{"exit-command-arg", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_exit_args,
"Additional arg to pass to the exit command. Can be specified multiple times", NULL},
{"exit-delay", 0, 0, G_OPTION_ARG_INT, &opt_exit_delay, "Delay before invoking the exit command (in seconds)", NULL},
{"exit-dir", 0, 0, G_OPTION_ARG_STRING, &opt_exit_dir, "Path to the directory where exit files are written", NULL},
{"leave-stdin-open", 0, 0, G_OPTION_ARG_NONE, &opt_leave_stdin_open, "Leave stdin open when attached client disconnects", NULL},
{"log-level", 0, 0, G_OPTION_ARG_STRING, &opt_log_level, "Print debug logs based on log level", NULL},
{"log-path", 'l', 0, G_OPTION_ARG_STRING_ARRAY, &opt_log_path, "Log file path", NULL},
{"log-size-max", 0, 0, G_OPTION_ARG_INT64, &opt_log_size_max, "Maximum size of log file", NULL},
{"log-global-size-max", 0, 0, G_OPTION_ARG_INT64, &opt_log_global_size_max, "Maximum size of all log files", NULL},
{"log-tag", 0, 0, G_OPTION_ARG_STRING, &opt_log_tag, "Additional tag to use for logging", NULL},
{"name", 'n', 0, G_OPTION_ARG_STRING, &opt_name, "Container name", NULL},
{"no-new-keyring", 0, 0, G_OPTION_ARG_NONE, &opt_no_new_keyring, "Do not create a new session keyring for the container", NULL},
{"no-pivot", 0, 0, G_OPTION_ARG_NONE, &opt_no_pivot, "Do not use pivot_root", NULL},
{"no-sync-log", 0, 0, G_OPTION_ARG_NONE, &opt_no_sync_log, "Do not manually call sync on logs after container shutdown", NULL},
{"persist-dir", '0', 0, G_OPTION_ARG_STRING, &opt_persist_path,
"Persistent directory for a container that can be used for storing container data", NULL},
{"pidfile", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &opt_container_pid_file, "PID file (DEPRECATED)", NULL},
{"replace-listen-pid", 0, 0, G_OPTION_ARG_NONE, &opt_replace_listen_pid, "Replace listen pid if set for oci-runtime pid", NULL},
{"restore", 0, 0, G_OPTION_ARG_STRING, &opt_restore_path, "Restore a container from a checkpoint", NULL},
{"restore-arg", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING_ARRAY, &opt_runtime_opts,
"Additional arg to pass to the restore command. Can be specified multiple times. (DEPRECATED)", NULL},
{"runtime", 'r', 0, G_OPTION_ARG_STRING, &opt_runtime_path, "Path to store runtime data for the container", NULL},
{"runtime-arg", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_runtime_args,
"Additional arg to pass to the runtime. Can be specified multiple times", NULL},
{"runtime-opt", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_runtime_opts,
"Additional opts to pass to the restore or exec command. Can be specified multiple times", NULL},
{"sdnotify-socket", 0, 0, G_OPTION_ARG_STRING, &opt_sdnotify_socket, "Path to the host's sd-notify socket to relay messages to",
NULL},
{"socket-dir-path", 0, 0, G_OPTION_ARG_STRING, &opt_socket_path, "Location of container attach sockets", NULL},
{"stdin", 'i', 0, G_OPTION_ARG_NONE, &opt_stdin, "Open up a pipe to pass stdin to the container", NULL},
{"sync", 0, 0, G_OPTION_ARG_NONE, &opt_sync, "Keep the main conmon process as its child by only forking once", NULL},
{"syslog", 0, 0, G_OPTION_ARG_NONE, &opt_syslog, "Log to syslog (use with cgroupfs cgroup manager)", NULL},
{"systemd-cgroup", 's', 0, G_OPTION_ARG_NONE, &opt_systemd_cgroup,
"Enable systemd cgroup manager, rather then use the cgroupfs directly", NULL},
{"terminal", 't', 0, G_OPTION_ARG_NONE, &opt_terminal, "Allocate a pseudo-TTY. The default is false", NULL},
{"timeout", 'T', 0, G_OPTION_ARG_INT, &opt_timeout, "Kill container after specified timeout in seconds.", NULL},
{"version", 0, 0, G_OPTION_ARG_NONE, &opt_version, "Print the version and exit", NULL},
{"full-attach", 0, 0, G_OPTION_ARG_NONE, &opt_full_attach_path,
"Don't truncate the path to the attach socket. This option causes conmon to ignore --socket-dir-path", NULL},
{"seccomp-notify-socket", 0, 0, G_OPTION_ARG_STRING, &opt_seccomp_notify_socket,
"Path to the socket where the seccomp notification fd is received", NULL},
{"seccomp-notify-plugins", 0, 0, G_OPTION_ARG_STRING, &opt_seccomp_notify_plugins,
"Plugins to use for managing the seccomp notifications", NULL},
{NULL, 0, 0, 0, NULL, NULL, NULL}};
int initialize_cli(int argc, char *argv[])
{
GOptionContext *context = g_option_context_new("- conmon utility");
g_option_context_add_main_entries(context, opt_entries, "conmon");
GError *error = NULL;
if (!g_option_context_parse(context, &argc, &argv, &error)) {
g_printerr("conmon: option parsing failed: %s\n", error->message);
exit(EXIT_FAILURE);
}
g_option_context_free(context);
context = NULL;
if (opt_version) {
g_print("conmon version " VERSION "\ncommit: " GIT_COMMIT "\n");
exit(EXIT_SUCCESS);
}
if (opt_cid == NULL) {
fprintf(stderr, "conmon: Container ID not provided. Use --cid\n");
exit(EXIT_FAILURE);
}
return -1;
}
void process_cli()
{
/* Command line parameters */
set_conmon_logs(opt_log_level, opt_cid, opt_syslog, opt_log_tag);
main_loop = g_main_loop_new(NULL, FALSE);
if (opt_restore_path && opt_exec)
nexit("Cannot use 'exec' and 'restore' at the same time");
if (!opt_exec && opt_attach)
nexit("Attach can only be specified with exec");
if (opt_api_version < 1 && opt_attach)
nexit("Attach can only be specified for a non-legacy exec session");
/* The old exec API did not require opt_cuuid */
if (opt_cuuid == NULL && (!opt_exec || opt_api_version >= 1))
nexit("Container UUID not provided. Use --cuuid");
if (opt_seccomp_notify_plugins == NULL)
opt_seccomp_notify_plugins = getenv("CONMON_SECCOMP_NOTIFY_PLUGINS");
if (opt_runtime_path == NULL)
nexit("Runtime path not provided. Use --runtime");
if (access(opt_runtime_path, X_OK) < 0)
pexitf("Runtime path %s is not valid", opt_runtime_path);
if (opt_exec && opt_exec_process_spec == NULL) {
nexit("Exec process spec path not provided. Use --exec-process-spec");
}
char cwd[PATH_MAX];
if (getcwd(cwd, sizeof(cwd)) == NULL) {
nexit("Failed to get working directory");
}
// opt_bundle_path in exec means we will set up the attach socket
// for the exec session. the legacy version of exec does not need this
// and thus we only override an empty opt_bundle_path when we're not exec
if (opt_bundle_path == NULL && !opt_exec) {
opt_bundle_path = cwd;
}
if (opt_exit_delay < 0) {
nexit("Delay before invoking exit command must be greater than or equal to 0");
}
// we should always override the container pid file if it's empty
// TODO FIXME I removed default_pid_file here. shouldn't opt_container_pid_file be cleaned up?
if (opt_container_pid_file == NULL)
opt_container_pid_file = g_strdup_printf("%s/pidfile-%s", cwd, opt_cid);
configure_log_drivers(opt_log_path, opt_log_size_max, opt_log_global_size_max, opt_cid, opt_name, opt_log_tag);
}
|