sync with openeuler on 03.14
Signed-off-by: gaohuatao <gaohuatao@huawei.com>
This commit is contained in:
parent
5d81a8d046
commit
7a82f9bc68
@ -63,8 +63,11 @@ RUN yum clean all && yum swap -y fakesystemd systemd && \
|
|||||||
gmock \
|
gmock \
|
||||||
gmock-devel \
|
gmock-devel \
|
||||||
cppcheck \
|
cppcheck \
|
||||||
|
python3 \
|
||||||
|
python3-pip \
|
||||||
python \
|
python \
|
||||||
python-pip \
|
python-pip \
|
||||||
|
device-mapper-devel \
|
||||||
libcurl-devel \
|
libcurl-devel \
|
||||||
zlib-devel \
|
zlib-devel \
|
||||||
glibc-headers \
|
glibc-headers \
|
||||||
|
|||||||
@ -23,7 +23,9 @@ $ sudo make
|
|||||||
$ sudo make install
|
$ sudo make install
|
||||||
```
|
```
|
||||||
|
|
||||||
## Via Docker container
|
## Trial iSulad Via Docker container
|
||||||
|
|
||||||
|
You can try to use iSulad via Docker container. The following steps guide you how to create a Docker container which can run iSulad inside.
|
||||||
|
|
||||||
#### Build image
|
#### Build image
|
||||||
|
|
||||||
@ -45,12 +47,12 @@ $ sudo mkdir -p /var/lib/isulad
|
|||||||
|
|
||||||
#### Build iSulad in container
|
#### Build iSulad in container
|
||||||
|
|
||||||
Let's suppose that you built an image called `iSulad:dev`.
|
Let's suppose that you built an image called `isulad:dev`.
|
||||||
|
|
||||||
Then from the iSulad source root directory you can run the following command:
|
Then from the iSulad source root directory you can run the following command:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ sudo docker run -tid --name YOUR_CONTAINER_NAME -v /var/lib/isulad:/var/lib/isulad -v `pwd`:/src/isulad --privileged iSulad:dev
|
$ sudo docker run -tid --name YOUR_CONTAINER_NAME -v /var/lib/isulad:/var/lib/isulad -v `pwd`:/src/isulad --privileged isulad:dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Let's suppose that you run an container named `iSulad_build`. Then you can use the following commands to build iSulad in your container `iSulad_build`:
|
Let's suppose that you run an container named `iSulad_build`. Then you can use the following commands to build iSulad in your container `iSulad_build`:
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
%global _version 1.1.12
|
%global _version 1.1.12
|
||||||
%global _release 20200306.143730.gitb83d1ed8
|
%global _release 20200311.212052.git8d13b09e
|
||||||
%global is_systemd 1
|
%global is_systemd 1
|
||||||
%global debug_package %{nil}
|
%global debug_package %{nil}
|
||||||
|
|
||||||
|
|||||||
@ -147,6 +147,7 @@ add_executable(isulad-shim
|
|||||||
${ISULAD_SHIM_SRCS}
|
${ISULAD_SHIM_SRCS}
|
||||||
${CMAKE_BINARY_DIR}/json/shim_client_process_state.c
|
${CMAKE_BINARY_DIR}/json/shim_client_process_state.c
|
||||||
${CMAKE_BINARY_DIR}/json/json_common.c
|
${CMAKE_BINARY_DIR}/json/json_common.c
|
||||||
|
${CMAKE_BINARY_DIR}/json/logger_json_file.c
|
||||||
${commonjsonsrcs}
|
${commonjsonsrcs}
|
||||||
)
|
)
|
||||||
target_include_directories(isulad-shim PUBLIC ${ISULAD_SHIM_INCS} ${SHARED_INCS})
|
target_include_directories(isulad-shim PUBLIC ${ISULAD_SHIM_INCS} ${SHARED_INCS})
|
||||||
|
|||||||
@ -153,10 +153,5 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
released_timeout_exit();
|
released_timeout_exit();
|
||||||
|
|
||||||
ret = process_signal_handle_routine(p);
|
return process_signal_handle_routine(p);
|
||||||
if (ret != SHIM_OK) {
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,9 +35,11 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
|
#include "terminal.h"
|
||||||
|
|
||||||
#define MAX_EVENTS 100
|
#define MAX_EVENTS 100
|
||||||
#define DEFAULT_IO_COPY_BUF (16*1024)
|
#define DEFAULT_IO_COPY_BUF (16*1024)
|
||||||
|
#define DEFAULT_LOG_FILE_SIZE (4*1024)
|
||||||
|
|
||||||
extern int g_log_fd;
|
extern int g_log_fd;
|
||||||
|
|
||||||
@ -143,6 +145,10 @@ static int add_io_dispatch(int epfd, io_thread_t *io_thd, int from, int to)
|
|||||||
return SHIM_ERR;
|
return SHIM_ERR;
|
||||||
}
|
}
|
||||||
fn->fd = to;
|
fn->fd = to;
|
||||||
|
fn->is_log = false;
|
||||||
|
if (io_thd->terminal != NULL && to == io_thd->terminal->fd) {
|
||||||
|
fn->is_log = true;
|
||||||
|
}
|
||||||
fn->next = NULL;
|
fn->next = NULL;
|
||||||
|
|
||||||
pthread_mutex_lock(&(ioc->mutex));
|
pthread_mutex_lock(&(ioc->mutex));
|
||||||
@ -254,11 +260,15 @@ static void* task_io_copy(void *data)
|
|||||||
} else {
|
} else {
|
||||||
fd_node_t *fn = ioc->fd_to;
|
fd_node_t *fn = ioc->fd_to;
|
||||||
for (; fn != NULL; fn = fn->next) {
|
for (; fn != NULL; fn = fn->next) {
|
||||||
int w_count;
|
if (fn->is_log) {
|
||||||
w_count = write_nointr(fn->fd, buf, r_count);
|
shim_write_container_log_file(io_thd->terminal, ioc->id == stdid_out ? "stdout" : "stderr", buf, r_count);
|
||||||
if (w_count < 0) {
|
} else {
|
||||||
// remove the write fd
|
int w_count = 0;
|
||||||
remove_io_dispatch(io_thd, -1, fn->fd);
|
w_count = write_nointr(fn->fd, buf, r_count);
|
||||||
|
if (w_count < 0) {
|
||||||
|
// remove the write fd
|
||||||
|
remove_io_dispatch(io_thd, -1, fn->fd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -318,6 +328,8 @@ static int process_io_start(process_t *p, int std_id)
|
|||||||
io_thd->epfd = p->io_loop_fd;
|
io_thd->epfd = p->io_loop_fd;
|
||||||
io_thd->ioc = ioc;
|
io_thd->ioc = ioc;
|
||||||
io_thd->shutdown = false;
|
io_thd->shutdown = false;
|
||||||
|
io_thd->terminal = std_id != stdid_in ? p->terminal : NULL;
|
||||||
|
|
||||||
p->io_threads[std_id] = io_thd;
|
p->io_threads[std_id] = io_thd;
|
||||||
|
|
||||||
ret = pthread_create(&(io_thd->tid), NULL, task_io_copy, io_thd);
|
ret = pthread_create(&(io_thd->tid), NULL, task_io_copy, io_thd);
|
||||||
@ -398,6 +410,9 @@ static int connect_to_isulad(process_t *p, int std_id, const char *isulad_stdio,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (*fd_from != -1) {
|
if (*fd_from != -1) {
|
||||||
|
if (std_id != stdid_in && p->io_threads[std_id]->terminal != NULL) {
|
||||||
|
(void)add_io_dispatch(p->io_loop_fd, p->io_threads[std_id], *fd_from, p->terminal->fd);
|
||||||
|
}
|
||||||
return add_io_dispatch(p->io_loop_fd, p->io_threads[std_id], *fd_from, *fd_to);
|
return add_io_dispatch(p->io_loop_fd, p->io_threads[std_id], *fd_from, *fd_to);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -677,11 +692,61 @@ static void adapt_for_isulad_stdin(process_t *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int terminal_init(log_terminal **terminal, shim_client_process_state *p_state)
|
||||||
|
{
|
||||||
|
log_terminal *log_term = NULL;
|
||||||
|
|
||||||
|
log_term = calloc(1, sizeof(log_terminal));
|
||||||
|
if (log_term == NULL) {
|
||||||
|
write_message(g_log_fd, ERR_MSG, "Failed to calloc log_terminal");
|
||||||
|
goto clean_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_rwlock_init(&log_term->log_terminal_rwlock, NULL) != 0) {
|
||||||
|
write_message(g_log_fd, ERR_MSG, "Failed to init isulad conf rwlock");
|
||||||
|
goto clean_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_state == NULL) {
|
||||||
|
goto clean_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_term->log_path = p_state->log_path;
|
||||||
|
/* Default to disable log. */
|
||||||
|
log_term->fd = -1;
|
||||||
|
log_term->log_maxfile = 1;
|
||||||
|
/* Default value 4k, the min size of a single log file */
|
||||||
|
log_term->log_maxsize = DEFAULT_LOG_FILE_SIZE;
|
||||||
|
|
||||||
|
if (p_state->log_maxfile > log_term->log_maxfile) {
|
||||||
|
log_term->log_maxfile = (unsigned int)p_state->log_maxfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_state->log_maxsize > log_term->log_maxsize) {
|
||||||
|
log_term->log_maxsize = (uint64_t)p_state->log_maxsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log_term->log_path != NULL) {
|
||||||
|
if (shim_create_container_log_file(log_term)) {
|
||||||
|
goto clean_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*terminal = log_term;
|
||||||
|
|
||||||
|
return SHIM_OK;
|
||||||
|
clean_out:
|
||||||
|
free(log_term);
|
||||||
|
*terminal = NULL;
|
||||||
|
return SHIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
process_t* new_process(char *id, char *bundle, char *runtime)
|
process_t* new_process(char *id, char *bundle, char *runtime)
|
||||||
{
|
{
|
||||||
shim_client_process_state* p_state;
|
shim_client_process_state* p_state;
|
||||||
process_t* p = NULL;
|
process_t* p = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
int ret;
|
||||||
|
|
||||||
p_state = load_process();
|
p_state = load_process();
|
||||||
if (p_state == NULL) {
|
if (p_state == NULL) {
|
||||||
@ -692,6 +757,13 @@ process_t* new_process(char *id, char *bundle, char *runtime)
|
|||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
ret = terminal_init(&(p->terminal), p_state);
|
||||||
|
if (ret != SHIM_OK) {
|
||||||
|
free(p);
|
||||||
|
p = NULL;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
p->id = id;
|
p->id = id;
|
||||||
p->bundle = bundle;
|
p->bundle = bundle;
|
||||||
p->runtime = runtime;
|
p->runtime = runtime;
|
||||||
@ -703,6 +775,7 @@ process_t* new_process(char *id, char *bundle, char *runtime)
|
|||||||
p->ctr_pid = -1;
|
p->ctr_pid = -1;
|
||||||
p->stdio = NULL;
|
p->stdio = NULL;
|
||||||
p->shim_io = NULL;
|
p->shim_io = NULL;
|
||||||
|
|
||||||
for (i = 0; i < 3; i ++) {
|
for (i = 0; i < 3; i ++) {
|
||||||
p->io_threads[i] = NULL;
|
p->io_threads[i] = NULL;
|
||||||
}
|
}
|
||||||
@ -726,7 +799,6 @@ int open_io(process_t *p)
|
|||||||
return open_generic_io(p);
|
return open_generic_io(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int process_io_init(process_t *p)
|
int process_io_init(process_t *p)
|
||||||
{
|
{
|
||||||
int ret = SHIM_ERR;
|
int ret = SHIM_ERR;
|
||||||
|
|||||||
@ -20,6 +20,7 @@
|
|||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "shim_client_process_state.h"
|
#include "shim_client_process_state.h"
|
||||||
|
#include "terminal.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -39,6 +40,7 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct fd_node {
|
typedef struct fd_node {
|
||||||
int fd;
|
int fd;
|
||||||
|
bool is_log;
|
||||||
struct fd_node *next;
|
struct fd_node *next;
|
||||||
} fd_node_t;
|
} fd_node_t;
|
||||||
|
|
||||||
@ -56,6 +58,7 @@ typedef struct {
|
|||||||
sem_t sem_thd;
|
sem_t sem_thd;
|
||||||
io_copy_t *ioc;
|
io_copy_t *ioc;
|
||||||
bool shutdown;
|
bool shutdown;
|
||||||
|
log_terminal *terminal;
|
||||||
} io_thread_t;
|
} io_thread_t;
|
||||||
|
|
||||||
typedef struct process {
|
typedef struct process {
|
||||||
@ -66,6 +69,7 @@ typedef struct process {
|
|||||||
int io_loop_fd;
|
int io_loop_fd;
|
||||||
int exit_fd;
|
int exit_fd;
|
||||||
int ctr_pid;
|
int ctr_pid;
|
||||||
|
log_terminal *terminal;
|
||||||
stdio_t *stdio;
|
stdio_t *stdio;
|
||||||
stdio_t *shim_io;
|
stdio_t *shim_io;
|
||||||
io_thread_t *io_threads[3];// stdin,stdout,stderr
|
io_thread_t *io_threads[3];// stdin,stdout,stderr
|
||||||
|
|||||||
318
src/cmd/isulad-shim/terminal.c
Normal file
318
src/cmd/isulad-shim/terminal.c
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
|
||||||
|
* iSulad licensed under the Mulan PSL v1.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
||||||
|
* You may obtain a copy of Mulan PSL v1 at:
|
||||||
|
* http://license.coscl.org.cn/MulanPSL
|
||||||
|
* 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 v1 for more details.
|
||||||
|
* Author: gaohuatao
|
||||||
|
* Create: 2020-3-9
|
||||||
|
* Description: container logs ops
|
||||||
|
******************************************************************************/
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include "terminal.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define BUF_CACHE_SIZE (16 * 1024)
|
||||||
|
|
||||||
|
static ssize_t shim_write_nointr_lock(log_terminal *terminal, const void *buf, size_t count)
|
||||||
|
{
|
||||||
|
ssize_t ret;
|
||||||
|
|
||||||
|
(void)pthread_rwlock_wrlock(&terminal->log_terminal_rwlock);
|
||||||
|
ret = write_nointr(terminal->fd, buf, count);
|
||||||
|
(void)pthread_rwlock_unlock(&terminal->log_terminal_rwlock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int shim_rename_old_log_file(log_terminal *terminal)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
unsigned int i;
|
||||||
|
char tmp[PATH_MAX] = {0};
|
||||||
|
char *rename_fname = NULL;
|
||||||
|
|
||||||
|
for (i = terminal->log_maxfile - 1; i > 1; i--) {
|
||||||
|
ret = snprintf(tmp, PATH_MAX, "%s.%u", terminal->log_path, i);
|
||||||
|
if (ret < 0 || ret >= PATH_MAX) {
|
||||||
|
free(rename_fname);
|
||||||
|
return SHIM_ERR;
|
||||||
|
}
|
||||||
|
free(rename_fname);
|
||||||
|
rename_fname = safe_strdup(tmp);
|
||||||
|
|
||||||
|
ret = snprintf(tmp, PATH_MAX, "%s.%u", terminal->log_path, (i - 1));
|
||||||
|
if (ret < 0 || ret >= PATH_MAX) {
|
||||||
|
free(rename_fname);
|
||||||
|
return SHIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = rename(tmp, rename_fname);
|
||||||
|
if (ret < 0 && errno != ENOENT) {
|
||||||
|
free(rename_fname);
|
||||||
|
return SHIM_ERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(rename_fname);
|
||||||
|
return SHIM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int shim_dump_log_file(log_terminal *terminal)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
char *file_newname;
|
||||||
|
size_t len_path = strlen(terminal->log_path) + sizeof(".1");
|
||||||
|
|
||||||
|
/* isulad: rotate old log file first */
|
||||||
|
ret = shim_rename_old_log_file(terminal);
|
||||||
|
if (ret != 0) {
|
||||||
|
return SHIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_newname = calloc(len_path, 1);
|
||||||
|
if (file_newname == NULL) {
|
||||||
|
return SHIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = snprintf(file_newname, len_path, "%s.1", terminal->log_path);
|
||||||
|
if (ret < 0 || (size_t)ret >= len_path) {
|
||||||
|
ret = -1;
|
||||||
|
goto clean_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Rename the file console.log to console.log.1 then create and open console.log again.
|
||||||
|
* fd points to console.log file always.
|
||||||
|
*/
|
||||||
|
close(terminal->fd);
|
||||||
|
terminal->fd = -1;
|
||||||
|
(void)rename(terminal->log_path, file_newname);
|
||||||
|
ret = shim_create_container_log_file(terminal);
|
||||||
|
clean_out:
|
||||||
|
free(file_newname);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t get_log_file_size(int fd)
|
||||||
|
{
|
||||||
|
struct stat log_st;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = fstat(fd, &log_st);
|
||||||
|
if (ret < 0) {
|
||||||
|
return SHIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (S_IFREG != (log_st.st_mode & S_IFMT)) {
|
||||||
|
return SHIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return log_st.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int shim_json_data_write(log_terminal *terminal, const char *buf,
|
||||||
|
int read_count)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int64_t available_space = -1;
|
||||||
|
int64_t file_size;
|
||||||
|
|
||||||
|
file_size = get_log_file_size(terminal->fd);
|
||||||
|
if (file_size < 0) {
|
||||||
|
return SHIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
available_space = terminal->log_maxsize - file_size;
|
||||||
|
if (read_count <= available_space) {
|
||||||
|
return shim_write_nointr_lock(terminal, buf, read_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = shim_dump_log_file(terminal);
|
||||||
|
if (ret < 0) {
|
||||||
|
return SHIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now file is new, then write the max bytes that will be wrote to log file.
|
||||||
|
* We have set the log file min size 16k, so the scenario of log_maxsize < read_count
|
||||||
|
* shouldn't happen, otherwise, discard some last bytes.
|
||||||
|
*/
|
||||||
|
ret = shim_write_nointr_lock(terminal, buf,
|
||||||
|
terminal->log_maxsize < read_count ? terminal->log_maxsize : read_count);
|
||||||
|
if (ret < 0) {
|
||||||
|
return SHIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (read_count - ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool get_time_buffer(struct timespec *timestamp, char *timebuffer,
|
||||||
|
size_t maxsize)
|
||||||
|
{
|
||||||
|
struct tm tm_utc = { 0 };
|
||||||
|
int32_t nanos = 0;
|
||||||
|
time_t seconds;
|
||||||
|
size_t len = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!timebuffer || !maxsize) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
seconds = (time_t)timestamp->tv_sec;
|
||||||
|
gmtime_r(&seconds, &tm_utc);
|
||||||
|
strftime(timebuffer, maxsize, "%Y-%m-%dT%H:%M:%S", &tm_utc);
|
||||||
|
|
||||||
|
nanos = (int32_t)timestamp->tv_nsec;
|
||||||
|
len = strlen(timebuffer);
|
||||||
|
ret = snprintf(timebuffer + len, (maxsize - len), ".%09dZ", nanos);
|
||||||
|
if (ret < 0 || ret >= (maxsize - len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool get_now_time_buffer(char *timebuffer, size_t maxsize)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
struct timespec ts;
|
||||||
|
|
||||||
|
err = clock_gettime(CLOCK_REALTIME, &ts);
|
||||||
|
if (err != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return get_time_buffer(&ts, timebuffer, maxsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t shim_logger_write(log_terminal *terminal, const char *type, const char *buf,
|
||||||
|
int read_count)
|
||||||
|
{
|
||||||
|
logger_json_file *msg = NULL;
|
||||||
|
ssize_t ret = -1;
|
||||||
|
size_t len;
|
||||||
|
char *json = NULL;
|
||||||
|
char timebuffer[64] = { 0 };
|
||||||
|
parser_error err = NULL;
|
||||||
|
struct parser_context ctx = { OPT_GEN_SIMPLIFY | OPT_GEN_NO_VALIDATE_UTF8, stderr };
|
||||||
|
|
||||||
|
if (read_count < 0 || read_count >= INT_MAX) {
|
||||||
|
return SHIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg = calloc(sizeof(logger_json_file), 1);
|
||||||
|
if (msg == NULL) {
|
||||||
|
return SHIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg->log = calloc(read_count, 1);
|
||||||
|
if (!msg->log) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
memcpy(msg->log, buf, read_count);
|
||||||
|
msg->log_len = read_count;
|
||||||
|
msg->stream = type ? safe_strdup(type) : safe_strdup("stdout");
|
||||||
|
|
||||||
|
get_now_time_buffer(timebuffer, sizeof(timebuffer));
|
||||||
|
msg->time = safe_strdup(timebuffer);
|
||||||
|
json = logger_json_file_generate_json(msg, &ctx, &err);
|
||||||
|
if (!json) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
len = strlen(json);
|
||||||
|
json[len] = '\n';
|
||||||
|
if (terminal->fd < 0) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = shim_json_data_write(terminal, json, len + 1);
|
||||||
|
cleanup:
|
||||||
|
free(json);
|
||||||
|
free_logger_json_file(msg);
|
||||||
|
free(err);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void shim_write_container_log_file(log_terminal *terminal, const char *type, char *buf,
|
||||||
|
int read_count)
|
||||||
|
{
|
||||||
|
static char cache[BUF_CACHE_SIZE];
|
||||||
|
static int size = 0;
|
||||||
|
int upto, index;
|
||||||
|
int begin = 0, buf_readed = 0, buf_left = 0;
|
||||||
|
|
||||||
|
if (terminal == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf != NULL && read_count > 0) {
|
||||||
|
upto = size + read_count;
|
||||||
|
if (upto > BUF_CACHE_SIZE) {
|
||||||
|
upto = BUF_CACHE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (upto > size) {
|
||||||
|
buf_readed = upto - size;
|
||||||
|
memcpy(cache + size, buf, buf_readed);
|
||||||
|
buf_left = read_count - buf_readed;
|
||||||
|
size += buf_readed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index = 0; index < size; index++) {
|
||||||
|
if (cache[index] == '\n') {
|
||||||
|
(void)shim_logger_write(terminal, type, cache + begin, index - begin + 1);
|
||||||
|
begin = index + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf == NULL || (begin == 0 && size == BUF_CACHE_SIZE)) {
|
||||||
|
if (begin < size) {
|
||||||
|
(void)shim_logger_write(terminal, type, cache + begin, size - begin);
|
||||||
|
begin = 0;
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
if (buf == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (begin > 0) {
|
||||||
|
memcpy(cache, cache + begin, size - begin);
|
||||||
|
size -= begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf_left > 0) {
|
||||||
|
memcpy(cache + size, buf + buf_readed, buf_left);
|
||||||
|
size += buf_left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int shim_create_container_log_file(log_terminal *terminal)
|
||||||
|
{
|
||||||
|
if (!terminal->log_path) {
|
||||||
|
return SHIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
terminal->fd = open(terminal->log_path, O_CLOEXEC | O_RDWR | O_CREAT | O_APPEND, 0600);
|
||||||
|
if (terminal->fd < 0) {
|
||||||
|
return SHIM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SHIM_OK;
|
||||||
|
}
|
||||||
|
|
||||||
48
src/cmd/isulad-shim/terminal.h
Normal file
48
src/cmd/isulad-shim/terminal.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
|
||||||
|
* iSulad licensed under the Mulan PSL v1.
|
||||||
|
* You can use this software according to the terms and conditions of the Mulan PSL v1.
|
||||||
|
* You may obtain a copy of Mulan PSL v1 at:
|
||||||
|
* http://license.coscl.org.cn/MulanPSL
|
||||||
|
* 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 v1 for more details.
|
||||||
|
* Author: gaohuatao
|
||||||
|
* Create: 2020-3-9
|
||||||
|
* Description: container logs ops
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __SHIM_TERMINAL_H
|
||||||
|
#define __SHIM_TERMINAL_H
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "logger_json_file.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PATH_MAX
|
||||||
|
#define PATH_MAX 4096
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t log_maxsize;
|
||||||
|
char *log_path;
|
||||||
|
int fd;
|
||||||
|
unsigned int log_maxfile;
|
||||||
|
pthread_rwlock_t log_terminal_rwlock;
|
||||||
|
} log_terminal;
|
||||||
|
|
||||||
|
void shim_write_container_log_file(log_terminal *terminal, const char *type, char *buf,
|
||||||
|
int bytes_read);
|
||||||
|
|
||||||
|
int shim_create_container_log_file(log_terminal *terminal);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __SHIM_TERMINAL_H */
|
||||||
@ -262,7 +262,7 @@ struct engine_operation *lcr_engine_init()
|
|||||||
{
|
{
|
||||||
void *lcr_handler = NULL;
|
void *lcr_handler = NULL;
|
||||||
struct engine_operation *eop = NULL;
|
struct engine_operation *eop = NULL;
|
||||||
lcr_handler = dlopen("liblcr.so", RTLD_NOW | RTLD_DEEPBIND);
|
lcr_handler = dlopen("liblcr.so", RTLD_NOW);
|
||||||
if (lcr_handler == NULL) {
|
if (lcr_handler == NULL) {
|
||||||
ERROR("Plugin error: %s", dlerror());
|
ERROR("Plugin error: %s", dlerror());
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@ -188,6 +188,15 @@
|
|||||||
},
|
},
|
||||||
"rootGID": {
|
"rootGID": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"logPath": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"logMaxfile": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"logMaxsize": {
|
||||||
|
"type": "int64"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,11 +28,14 @@
|
|||||||
#include "shim_client_process_state.h"
|
#include "shim_client_process_state.h"
|
||||||
#include "oci_runtime_state.h"
|
#include "oci_runtime_state.h"
|
||||||
#include "isulad_config.h"
|
#include "isulad_config.h"
|
||||||
|
#include "utils_string.h"
|
||||||
|
#include "libisulad.h"
|
||||||
|
|
||||||
#define SHIM_BINARY "isulad-shim"
|
#define SHIM_BINARY "isulad-shim"
|
||||||
#define SHIM_LOG_SIZE ((BUFSIZ-100)/2)
|
#define SHIM_LOG_SIZE ((BUFSIZ-100)/2)
|
||||||
#define PID_WAIT_TIME 120
|
#define PID_WAIT_TIME 120
|
||||||
|
|
||||||
|
|
||||||
static void copy_process(shim_client_process_state *p, defs_process *dp)
|
static void copy_process(shim_client_process_state *p, defs_process *dp)
|
||||||
{
|
{
|
||||||
p->args = dp->args;
|
p->args = dp->args;
|
||||||
@ -52,6 +55,31 @@ static void copy_process(shim_client_process_state *p, defs_process *dp)
|
|||||||
p->rlimits_len = dp->rlimits_len;
|
p->rlimits_len = dp->rlimits_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void copy_annotations(shim_client_process_state *p, json_map_string_string *anno)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
if (anno == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < anno->len; i++) {
|
||||||
|
if (strcmp(anno->keys[i], CONTAINER_LOG_CONFIG_KEY_FILE) == 0) {
|
||||||
|
p->log_path = anno->values[i];
|
||||||
|
} else if (strcmp(anno->keys[i], CONTAINER_LOG_CONFIG_KEY_ROTATE) == 0) {
|
||||||
|
int tmaxfile = 0;
|
||||||
|
if (util_safe_int(anno->values[i], &tmaxfile) == 0 && tmaxfile > 0) {
|
||||||
|
p->log_maxfile = tmaxfile;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strcmp(anno->keys[i], CONTAINER_LOG_CONFIG_KEY_SIZE) == 0) {
|
||||||
|
int64_t tmaxsize = 0;
|
||||||
|
if (util_parse_byte_size_string(anno->values[i], &tmaxsize) == 0 && tmaxsize > 0) {
|
||||||
|
p->log_maxsize = tmaxsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int file_write_int(const char *fname, int val)
|
static int file_write_int(const char *fname, int val)
|
||||||
{
|
{
|
||||||
char sint[UINT_LEN] = {0};
|
char sint[UINT_LEN] = {0};
|
||||||
@ -731,6 +759,7 @@ int rt_isula_create(const char *id, const char *runtime,
|
|||||||
p.runtime_args = (char **)runtime_args;
|
p.runtime_args = (char **)runtime_args;
|
||||||
p.runtime_args_len = runtime_args_len;
|
p.runtime_args_len = runtime_args_len;
|
||||||
copy_process(&p, config->process);
|
copy_process(&p, config->process);
|
||||||
|
copy_annotations(&p, config->annotations);
|
||||||
|
|
||||||
ret = create_process_json_file(workdir, &p);
|
ret = create_process_json_file(workdir, &p);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
|
|||||||
@ -255,7 +255,7 @@ static int umount_dev_tmpfs_for_system_container(const container_t *cont)
|
|||||||
ERROR("Out of memory");
|
ERROR("Out of memory");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (umount(rootfs_dev_path) < 0 && errno != EINVAL) {
|
if (umount(rootfs_dev_path) < 0 && errno != ENOENT) {
|
||||||
ERROR("Failed to umount dev tmpfs: %s, error: %s", rootfs_dev_path, strerror(errno));
|
ERROR("Failed to umount dev tmpfs: %s, error: %s", rootfs_dev_path, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -356,39 +356,49 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int merge_exec_process_env(defs_process *spec, const container_config *container_spec, const char **env,
|
static int merge_exec_from_container_env(defs_process *spec, const container_config *container_spec)
|
||||||
size_t env_len)
|
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
size_t env_count = 0;
|
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
if (env_len > LIST_ENV_SIZE_MAX - container_spec->env_len) {
|
if (container_spec->env_len > LIST_ENV_SIZE_MAX - spec->env_len) {
|
||||||
ERROR("The length of envionment variables is too long, the limit is %d", LIST_ENV_SIZE_MAX);
|
ERROR("The length of envionment variables is too long, the limit is %d", LIST_ENV_SIZE_MAX);
|
||||||
isulad_set_error_message("The length of envionment variables is too long, the limit is %d", LIST_ENV_SIZE_MAX);
|
isulad_set_error_message("The length of envionment variables is too long, the limit is %d", LIST_ENV_SIZE_MAX);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
env_count = container_spec->env_len + env_len;
|
|
||||||
if (env_count == 0) {
|
for (i = 0; i < container_spec->env_len; i++) {
|
||||||
ret = 0;
|
ret = util_array_append(&(spec->env), container_spec->env[i]);
|
||||||
goto out;
|
if (ret != 0) {
|
||||||
|
ERROR("Failed to append container env to exec process env");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
spec->env_len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
spec->env = util_common_calloc_s(env_count * sizeof(char *));
|
out:
|
||||||
if (spec->env == NULL) {
|
return ret;
|
||||||
ERROR("Failed to malloc memory for envionment variables");
|
}
|
||||||
|
|
||||||
|
static int merge_envs_from_request_env(defs_process *spec, const char **envs, size_t env_len)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
size_t i = 0;
|
||||||
|
|
||||||
|
if (env_len > LIST_ENV_SIZE_MAX - spec->env_len) {
|
||||||
|
ERROR("The length of envionment variables is too long, the limit is %d", LIST_ENV_SIZE_MAX);
|
||||||
|
isulad_set_error_message("The length of envionment variables is too long, the limit is %d", LIST_ENV_SIZE_MAX);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < container_spec->env_len; i++) {
|
|
||||||
spec->env[spec->env_len] = util_strdup_s(container_spec->env[i]);
|
|
||||||
spec->env_len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < env_len; i++) {
|
for (i = 0; i < env_len; i++) {
|
||||||
spec->env[spec->env_len] = util_strdup_s(env[i]);
|
ret = util_array_append(&(spec->env), envs[i]);
|
||||||
|
if (ret != 0) {
|
||||||
|
ERROR("Failed to append request env to exec process env");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
spec->env_len++;
|
spec->env_len++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,7 +443,7 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static defs_process *make_exec_process_spec(const container_config *container_spec, defs_process_user *puser,
|
static defs_process *make_exec_process_spec(const container_config *container_spec, defs_process_user *puser,
|
||||||
const container_exec_request *request)
|
const char *runtime, const container_exec_request *request)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
defs_process *spec = NULL;
|
defs_process *spec = NULL;
|
||||||
@ -443,16 +453,26 @@ static defs_process *make_exec_process_spec(const container_config *container_sp
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = merge_exec_process_env(spec, container_spec, (const char **)request->env, request->env_len);
|
if (strcasecmp(runtime, "lcr") != 0) {
|
||||||
|
ret = merge_exec_from_container_env(spec, container_spec);
|
||||||
|
if (ret != 0) {
|
||||||
|
ERROR("Failed to dup args for exec process spec");
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = merge_envs_from_request_env(spec, (const char **)request->env, request->env_len);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
ERROR("Failed to dup args for exec process spec");
|
ERROR("Failed to dup args for exec process spec");
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = append_necessary_process_env(request->tty, container_spec, spec);
|
if (strcasecmp(runtime, "lcr") != 0) {
|
||||||
if (ret != 0) {
|
ret = append_necessary_process_env(request->tty, container_spec, spec);
|
||||||
ERROR("Failed to append necessary for exec process spec");
|
if (ret != 0) {
|
||||||
goto err_out;
|
ERROR("Failed to append necessary for exec process spec");
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = dup_array_of_strings((const char **)request->argv, request->argv_len, &(spec->args), &(spec->args_len));
|
ret = dup_array_of_strings((const char **)request->argv, request->argv_len, &(spec->args), &(spec->args_len));
|
||||||
@ -507,7 +527,7 @@ static int exec_container(container_t *cont, const char *runtime, char * const c
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
process_spec = make_exec_process_spec(cont->common_config->config, puser, request);
|
process_spec = make_exec_process_spec(cont->common_config->config, puser, runtime, request);
|
||||||
if (process_spec == NULL) {
|
if (process_spec == NULL) {
|
||||||
ERROR("Exec: Failed to make process spec");
|
ERROR("Exec: Failed to make process spec");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|||||||
@ -116,6 +116,9 @@ bool get_timestamp(const char *str_time, types_timestamp_t *timestamp)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set tm_isdst be kept as -1 to let the system decide if its dst or not
|
||||||
|
tm_day.tm_isdst = -1;
|
||||||
|
|
||||||
seconds = (int64_t)mktime(&tm_day);
|
seconds = (int64_t)mktime(&tm_day);
|
||||||
timestamp->has_seconds = true;
|
timestamp->has_seconds = true;
|
||||||
timestamp->seconds = seconds;
|
timestamp->seconds = seconds;
|
||||||
@ -559,7 +562,11 @@ static int64_t get_minmus_time(struct tm *tm1, struct tm *tm2)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set tm_isdst be kept as -1 to let the system decide if its dst or not
|
||||||
|
tm1->tm_isdst = -1;
|
||||||
tmseconds1 = (int64_t)mktime(tm1);
|
tmseconds1 = (int64_t)mktime(tm1);
|
||||||
|
// set tm_isdst be kept as -1 to let the system decide if its dst or not
|
||||||
|
tm2->tm_isdst = -1;
|
||||||
tmseconds2 = (int64_t)mktime(tm2);
|
tmseconds2 = (int64_t)mktime(tm2);
|
||||||
result = tmseconds1 - tmseconds2;
|
result = tmseconds1 - tmseconds2;
|
||||||
return result;
|
return result;
|
||||||
@ -911,6 +918,10 @@ int to_unix_nanos_from_str(const char *str, int64_t *nanos)
|
|||||||
ERROR("Transform str to timestamp failed");
|
ERROR("Transform str to timestamp failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set tm_isdst be kept as -1 to let the system decide if its dst or not
|
||||||
|
tm.tm_isdst = -1;
|
||||||
|
|
||||||
*nanos = mktime(&tm) * Time_Second + nano;
|
*nanos = mktime(&tm) * Time_Second + nano;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user