iSulad/src/runtime/lcr/lcr_rt_ops.c
LiFeng 5bd893e34e iSulad: adapt kata based on next_openeuler
Change-Id: Ia37071fce115de96e5e139369011451457caf714
Signed-off-by: LiFeng <lifeng68@huawei.com>
2020-02-12 22:55:13 -05:00

616 lines
20 KiB
C

/******************************************************************************
* Copyright (c) Huawei Technologies Co., Ltd. 2019. 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: lifeng
* Create: 2019-11-22
* Description: provide container list callback function definition
********************************************************************************/
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include "lcr_rt_ops.h"
#include "log.h"
#include "engine.h"
#include "callback.h"
#include "error.h"
#include "isulad_config.h"
#include "runtime.h"
bool rt_lcr_detect(const char *runtime)
{
/* now we just support lcr engine */
if (runtime != NULL && strcasecmp(runtime, "lcr") == 0) {
return true;
}
return false;
}
int rt_lcr_create(const char *name, const char *runtime, const rt_create_params_t *params)
{
int ret = 0;
char *runtime_root = NULL;
struct engine_operation *engine_ops = NULL;
runtime_root = conf_get_routine_rootdir(runtime);
if (runtime_root == NULL) {
ERROR("Root path is NULL");
ret = -1;
goto out;
}
engine_ops = engines_get_handler(runtime);
if (engine_ops == NULL || engine_ops->engine_create_op == NULL) {
ERROR("Failed to get engine create operations");
ret = -1;
goto out;
}
if (!engine_ops->engine_create_op(name, runtime_root, params->oci_config_data)) {
ERROR("Failed to create container");
const char *tmpmsg = NULL;
tmpmsg = engine_ops->engine_get_errmsg_op();
isulad_set_error_message("Create container error: %s",
(tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg
: DEF_ERR_RUNTIME_STR);
ret = -1;
goto out;
}
out:
if (engine_ops != NULL) {
engine_ops->engine_clear_errmsg_op();
}
free(runtime_root);
return ret;
}
static int parse_container_pid(const char *S, container_pid_t *pid_info)
{
int num;
num = sscanf(S, "%d %Lu %d %Lu", &pid_info->pid, &pid_info->start_time, &pid_info->ppid, &pid_info->pstart_time);
if (num != 4) { // args num to read is 4
ERROR("Call sscanf error: %s", errno ? strerror(errno) : "");
return -1;
}
return 0;
}
static int lcr_rt_read_pidfile(const char *pidfile, container_pid_t *pid_info)
{
if (pidfile == NULL || pid_info == NULL) {
ERROR("Invalid input arguments");
return -1;
}
char sbuf[1024] = { 0 }; /* bufs for stat */
if ((util_file2str(pidfile, sbuf, sizeof(sbuf))) == -1) {
return -1;
}
return parse_container_pid(sbuf, pid_info);
}
int rt_lcr_start(const char *name, const char *runtime, const rt_start_params_t *params, container_pid_t *pid_info)
{
int ret = 0;
struct engine_operation *engine_ops = NULL;
engine_start_request_t request = { 0 };
engine_ops = engines_get_handler(runtime);
if (engine_ops == NULL || engine_ops->engine_start_op == NULL) {
ERROR("Failed to get engine start operations");
ret = -1;
goto out;
}
request.name = name;
request.lcrpath = params->rootpath;
request.logpath = params->logpath;
request.loglevel = params->loglevel;
request.daemonize = true;
request.tty = params->tty;
request.open_stdin = params->open_stdin;
request.console_fifos = params->console_fifos;
request.start_timeout = params->start_timeout;
request.container_pidfile = params->container_pidfile;
request.exit_fifo = params->exit_fifo;
if (!engine_ops->engine_start_op(&request)) {
const char *tmpmsg = NULL;
tmpmsg = engine_ops->engine_get_errmsg_op();
isulad_set_error_message("Start container error: %s",
(tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg
: DEF_ERR_RUNTIME_STR);
ERROR("Start container error: %s", (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg
: DEF_ERR_RUNTIME_STR);
ret = -1;
goto out;
}
ret = lcr_rt_read_pidfile(params->container_pidfile, pid_info);
if (ret != 0) {
ERROR("Failed to get started container's pid info, start container fail");
ret = -1;
goto out;
}
out:
if (engine_ops != NULL) {
engine_ops->engine_clear_errmsg_op();
}
return ret;
}
int rt_lcr_restart(const char *name, const char *runtime, const rt_restart_params_t *params)
{
return RUNTIME_NOT_IMPLEMENT_RESET;
}
int rt_lcr_clean_resource(const char *name, const char *runtime, const rt_clean_params_t *params)
{
int ret = 0;
struct engine_operation *engine_ops = NULL;
engine_ops = engines_get_handler(runtime);
if (engine_ops == NULL || engine_ops->engine_clean_op == NULL) {
ERROR("Failed to get engine clean operations");
ret = -1;
goto out;
}
if (!engine_ops->engine_clean_op(name, params->rootpath, params->logpath, params->loglevel, params->pid)) {
const char *tmpmsg = NULL;
tmpmsg = engine_ops->engine_get_errmsg_op();
isulad_try_set_error_message("Clean resource container error;%s",
(tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg
: DEF_ERR_RUNTIME_STR);
ret = -1;
goto out;
}
out:
if (engine_ops != NULL) {
engine_ops->engine_clear_errmsg_op();
}
return ret;
}
static int remove_container_rootpath(const char *id, const char *root_path)
{
int ret = 0;
char cont_root_path[PATH_MAX] = { 0 };
ret = snprintf(cont_root_path, sizeof(cont_root_path), "%s/%s", root_path, id);
if (ret < 0 || (size_t)ret >= sizeof(cont_root_path)) {
ERROR("Failed to sprintf container_state");
ret = -1;
goto out;
}
ret = util_recursive_rmdir(cont_root_path, 0);
if (ret != 0) {
const char *tmp_err = (errno != 0) ? strerror(errno) : "error";
ERROR("Failed to delete container's root directory %s: %s", cont_root_path, tmp_err);
isulad_set_error_message("Failed to delete container's root directory %s: %s", cont_root_path, tmp_err);
ret = -1;
goto out;
}
out:
return ret;
}
int rt_lcr_rm(const char *name, const char *runtime, const rt_rm_params_t *params)
{
int ret = 0;
struct engine_operation *engine_ops = NULL;
engine_ops = engines_get_handler(runtime);
if (engine_ops == NULL || engine_ops->engine_delete_op == NULL) {
ERROR("Failed to get engine delete operations");
ret = -1;
goto out;
}
if (!engine_ops->engine_delete_op(name, params->rootpath)) {
ret = -1;
const char *tmpmsg = engine_ops->engine_get_errmsg_op();
isulad_set_error_message("Runtime delete container error: %s",
(tmpmsg != NULL && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg : DEF_ERR_RUNTIME_STR);
ERROR("Runtime delete container error: %s",
(tmpmsg != NULL && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg : DEF_ERR_RUNTIME_STR);
if (tmpmsg != NULL && strstr(tmpmsg, "No such container") != NULL) {
// container root path may been corrupted, try to remove by daemon
WARN("container %s root path may been corrupted, try to remove by daemon", name);
if (remove_container_rootpath(name, params->rootpath) == 0) {
ret = 0;
goto out;
}
}
goto out;
}
out:
if (engine_ops != NULL) {
engine_ops->engine_clear_errmsg_op();
}
return ret;
}
int rt_lcr_status(const char *name, const char *runtime, const rt_status_params_t *params,
struct engine_container_status_info *status)
{
int ret = 0;
int nret = 0;
struct engine_operation *engine_ops = NULL;
engine_ops = engines_get_handler(runtime);
if (engine_ops == NULL || engine_ops->engine_get_container_status_op == NULL) {
ERROR("Failed to get engine status operations");
ret = -1;
goto out;
}
nret = engine_ops->engine_get_container_status_op(name, params->rootpath, status);
if (nret != 0) {
engine_ops->engine_clear_errmsg_op();
ret = -1;
goto out;
}
out:
if (engine_ops != NULL) {
engine_ops->engine_clear_errmsg_op();
}
return ret;
}
int rt_lcr_resources_stats(const char *name, const char *runtime, const rt_stats_params_t *params,
struct engine_container_resources_stats_info *rs_stats)
{
int ret = 0;
int nret = 0;
struct engine_operation *engine_ops = NULL;
engine_ops = engines_get_handler(runtime);
if (engine_ops == NULL || engine_ops->engine_get_container_resources_stats_op == NULL) {
ERROR("Failed to get engine stats operations");
ret = -1;
goto out;
}
nret = engine_ops->engine_get_container_resources_stats_op(name, params->rootpath, rs_stats);
if (nret != 0) {
engine_ops->engine_clear_errmsg_op();
ret = -1;
goto out;
}
out:
if (engine_ops != NULL) {
engine_ops->engine_clear_errmsg_op();
}
return ret;
}
// user string(UID:GID)
static int generate_user_string_by_uid_gid(const defs_process_user *puser, char **user)
{
char uid_str[ISULAD_NUMSTRLEN32] = { 0 };
char gid_str[ISULAD_NUMSTRLEN32] = { 0 };
size_t len;
int nret = 0;
nret = snprintf(uid_str, ISULAD_NUMSTRLEN32, "%u", (unsigned int)puser->uid);
if (nret < 0 || nret >= ISULAD_NUMSTRLEN32) {
ERROR("Invalid UID:%u", (unsigned int)puser->uid);
return -1;
}
nret = snprintf(gid_str, ISULAD_NUMSTRLEN32, "%u", (unsigned int)puser->gid);
if (nret < 0 || nret >= ISULAD_NUMSTRLEN32) {
ERROR("Invalid attach uid value :%u", (unsigned int)puser->gid);
return -1;
}
len = strlen(uid_str) + 1 + strlen(gid_str) + 1;
*user = (char *)util_common_calloc_s(len * sizeof(char));
if (*user == NULL) {
ERROR("Out of memory");
return -1;
}
nret = snprintf(*user, len, "%u:%u", (unsigned int)puser->uid, (unsigned int)puser->gid);
if (nret < 0 || (size_t)nret >= len) {
ERROR("Invalid UID:GID (%u:%u)", (unsigned int)puser->uid, (unsigned int)puser->gid);
free(*user);
*user = NULL;
return -1;
}
return 0;
}
int rt_lcr_exec(const char *id, const char *runtime, const rt_exec_params_t *params, int *exit_code)
{
int ret = 0;
struct engine_operation *engine_ops = NULL;
engine_exec_request_t request = { 0 };
char *user = NULL;
engine_ops = engines_get_handler(runtime);
if (engine_ops == NULL || engine_ops->engine_exec_op == NULL) {
DEBUG("Failed to get engine exec operations");
ret = -1;
goto out;
}
request.name = id;
request.lcrpath = params->rootpath;
request.logpath = params->logpath;
request.loglevel = params->loglevel;
request.args = (const char **)params->spec->args;
request.args_len = params->spec->args_len;
request.env = (const char **)params->spec->env;
request.env_len = params->spec->env_len;
request.console_fifos = params->console_fifos;
request.timeout = params->timeout;
request.suffix = params->suffix;
if (params->spec->user != NULL) {
if (generate_user_string_by_uid_gid(params->spec->user, &user) != 0) {
ret = -1;
goto out;
}
request.user = user;
}
if (!engine_ops->engine_exec_op(&request, exit_code)) {
const char *tmpmsg = NULL;
tmpmsg = engine_ops->engine_get_errmsg_op();
isulad_set_error_message("Exec container error;%s", (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ?
tmpmsg : DEF_ERR_RUNTIME_STR);
util_contain_errmsg(g_isulad_errmsg, exit_code);
ret = -1;
goto out;
}
out:
if (engine_ops != NULL) {
engine_ops->engine_clear_errmsg_op();
}
free(user);
return ret;
}
int rt_lcr_pause(const char *name, const char *runtime, const rt_pause_params_t *params)
{
int ret = 0;
struct engine_operation *engine_ops = NULL;
engine_ops = engines_get_handler(runtime);
if (engine_ops == NULL || engine_ops->engine_pause_op == NULL) {
DEBUG("Failed to get engine pause operations");
ret = -1;
goto out;
}
if (!engine_ops->engine_pause_op(name, params->rootpath)) {
DEBUG("Pause container %s failed", name);
const char *tmpmsg = NULL;
tmpmsg = engine_ops->engine_get_errmsg_op();
isulad_set_error_message("Pause container error;%s", (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ?
tmpmsg : DEF_ERR_RUNTIME_STR);
ret = -1;
goto out;
}
out:
if (engine_ops != NULL) {
engine_ops->engine_clear_errmsg_op();
}
return ret;
}
int rt_lcr_resume(const char *name, const char *runtime, const rt_resume_params_t *params)
{
int ret = 0;
struct engine_operation *engine_ops = NULL;
engine_ops = engines_get_handler(runtime);
if (engine_ops == NULL || engine_ops->engine_resume_op == NULL) {
DEBUG("Failed to get engine resume operations");
ret = -1;
goto out;
}
if (!engine_ops->engine_resume_op(name, params->rootpath)) {
DEBUG("Resume container %s failed", name);
const char *tmpmsg = NULL;
tmpmsg = engine_ops->engine_get_errmsg_op();
isulad_set_error_message("Resume container error;%s",
(tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg
: DEF_ERR_RUNTIME_STR);
ret = -1;
goto out;
}
out:
if (engine_ops != NULL) {
engine_ops->engine_clear_errmsg_op();
}
return ret;
}
int rt_lcr_attach(const char *name, const char *runtime, const rt_attach_params_t *params)
{
int ret = 0;
struct engine_operation *engine_ops = NULL;
engine_ops = engines_get_handler(runtime);
if (engine_ops == NULL || engine_ops->engine_console_op == NULL) {
DEBUG("Failed to get engine attach operations");
ret = -1;
goto out;
}
if (!engine_ops->engine_console_op(name, params->rootpath, (char *)params->stdin, (char *)params->stdout,
(char *)params->stderr)) {
ERROR("attach failed");
const char *tmpmsg = NULL;
tmpmsg = engine_ops->engine_get_errmsg_op();
isulad_set_error_message("Attach container error;%s", (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ?
tmpmsg : DEF_ERR_RUNTIME_STR);
ret = -1;
goto out;
}
out:
if (engine_ops != NULL) {
engine_ops->engine_clear_errmsg_op();
}
return ret;
}
static void to_engine_resources(const host_config *hostconfig, struct engine_cgroup_resources *cr)
{
if (hostconfig == NULL || cr == NULL) {
return;
}
cr->blkio_weight = hostconfig->blkio_weight;
cr->cpu_shares = (uint64_t)hostconfig->cpu_shares;
cr->cpu_period = (uint64_t)hostconfig->cpu_period;
cr->cpu_quota = (uint64_t)hostconfig->cpu_quota;
cr->cpuset_cpus = hostconfig->cpuset_cpus;
cr->cpuset_mems = hostconfig->cpuset_mems;
cr->memory_limit = (uint64_t)hostconfig->memory;
cr->memory_swap = (uint64_t)hostconfig->memory_swap;
cr->memory_reservation = (uint64_t)hostconfig->memory_reservation;
cr->kernel_memory_limit = (uint64_t)hostconfig->kernel_memory;
}
int rt_lcr_update(const char *id, const char *runtime, const rt_update_params_t *params)
{
int ret = 0;
struct engine_operation *engine_ops = NULL;
struct engine_cgroup_resources cr = { 0 };
engine_ops = engines_get_handler(runtime);
if (engine_ops == NULL || engine_ops->engine_update_op == NULL) {
DEBUG("Failed to get engine update operations");
ret = -1;
goto out;
}
to_engine_resources(params->hostconfig, &cr);
if (!engine_ops->engine_update_op(id, params->rootpath, &cr)) {
DEBUG("Update container %s failed", id);
const char *tmpmsg = NULL;
tmpmsg = engine_ops->engine_get_errmsg_op();
isulad_set_error_message("Cannot update container %s: %s", id, (tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ?
tmpmsg : DEF_ERR_RUNTIME_STR);
ret = -1;
goto out;
}
out:
if (engine_ops != NULL) {
engine_ops->engine_clear_errmsg_op();
}
return ret;
}
int rt_lcr_listpids(const char *name, const char *runtime, const rt_listpids_params_t *params, rt_listpids_out_t *out)
{
int ret = 0;
struct engine_operation *engine_ops = NULL;
engine_ops = engines_get_handler(runtime);
if (engine_ops == NULL || engine_ops->engine_get_container_pids_op == NULL) {
DEBUG("Failed to get engine top operations");
ret = -1;
goto out;
}
if (!engine_ops->engine_get_container_pids_op(name, params->rootpath, &(out->pids), &(out->pids_len))) {
DEBUG("Top container %s failed", name);
const char *tmpmsg = NULL;
tmpmsg = engine_ops->engine_get_errmsg_op();
isulad_set_error_message("Runtime top container error: %s",
(tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg : DEF_ERR_RUNTIME_STR);
ret = -1;
goto out;
}
out:
if (engine_ops != NULL) {
engine_ops->engine_clear_errmsg_op();
}
return ret;
}
int rt_lcr_resize(const char *id, const char *runtime, const rt_resize_params_t *params)
{
int ret = 0;
struct engine_operation *engine_ops = NULL;
engine_ops = engines_get_handler(runtime);
if (engine_ops == NULL || engine_ops->engine_resize_op == NULL) {
DEBUG("Failed to get engine resume operations");
ret = -1;
goto out;
}
if (!engine_ops->engine_resize_op(id, params->rootpath, params->height, params->width)) {
DEBUG("resize container %s failed", id);
const char *tmpmsg = NULL;
tmpmsg = engine_ops->engine_get_errmsg_op();
isulad_set_error_message("Resize container error;%s",
(tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg
: DEF_ERR_RUNTIME_STR);
ret = -1;
goto out;
}
out:
if (engine_ops != NULL) {
engine_ops->engine_clear_errmsg_op();
}
return ret;
}
int rt_lcr_exec_resize(const char *id, const char *runtime, const rt_exec_resize_params_t *params)
{
int ret = 0;
struct engine_operation *engine_ops = NULL;
engine_ops = engines_get_handler(runtime);
if (engine_ops == NULL || engine_ops->engine_resize_op == NULL) {
DEBUG("Failed to get engine resume operations");
ret = -1;
goto out;
}
if (!engine_ops->engine_exec_resize_op(id, params->rootpath, params->suffix, params->height, params->width)) {
DEBUG("exec resize container %s failed", id);
const char *tmpmsg = NULL;
tmpmsg = engine_ops->engine_get_errmsg_op();
isulad_set_error_message("Resize container error;%s",
(tmpmsg && strcmp(tmpmsg, DEF_SUCCESS_STR)) ? tmpmsg
: DEF_ERR_RUNTIME_STR);
ret = -1;
goto out;
}
out:
if (engine_ops != NULL) {
engine_ops->engine_clear_errmsg_op();
}
return ret;
}